From 01b91deec7b6113ae728ac3f7a55f64f57ddb3e0 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Thu, 30 Nov 2023 07:04:20 -0600 Subject: fix(treesitter): fix parens stacking in inspector display (#26304) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When first opened, the tree-sitter inspector traverses all of the nodes in the buffer to calculate an array of nodes. This traversal is done only once, and _all_ nodes (both named and anonymous) are included. Toggling anonymous nodes in the inspector only changes how the tree is drawn in the buffer, but does not affect the underlying data structure at all. When the buffer is traversed and the list of nodes is calculated, we don't know whether or not anonymous nodes will be displayed in the inspector or not. Thus, we cannot determine during traversal where to put closing parentheses. Instead, this must be done when drawing. When we draw, the tree structure has been flatted into a single array, so we lose parent-child relationships that would otherwise make determining the number of closing parentheses straightforward. However, we can instead rely on the fact that a delta between the depth of a node and the depth of the successive node _must_ mean that more closing parentheses are required: (foo (bar) (baz) ↑ │ └ (bar) and (baz) have different depths, so (bar) must have an extra closing parenthesis This does not depend on whether or not anonymous nodes are displayed and so works in both cases. --- runtime/lua/vim/treesitter/dev.lua | 103 ++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 53 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 69ddc9b558..aad639d85a 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -14,16 +14,12 @@ local M = {} local TSTreeView = {} ---@class TSP.Node ----@field id integer Node id ----@field text string Node text ----@field named boolean True if this is a named (non-anonymous) node ----@field depth integer Depth of the node within the tree ----@field lnum integer Beginning line number of this node in the source buffer ----@field col integer Beginning column number of this node in the source buffer ----@field end_lnum integer Final line number of this node in the source buffer ----@field end_col integer Final column number of this node in the source buffer +---@field node TSNode Tree-sitter node +---@field field string? Node field +---@field depth integer Depth of this node in the tree +---@field text string? Text displayed in the inspector for this node. Not computed until the +--- inspector is drawn. ---@field lang string Source language of this node ----@field root TSNode ---@class TSP.Injection ---@field lang string Source language of this injection @@ -54,37 +50,14 @@ local function traverse(node, depth, lang, injections, tree) end for child, field in node:iter_children() do - local type = child:type() - local lnum, col, end_lnum, end_col = child:range() - local named = child:named() - local text ---@type string - if named then - if field then - text = string.format('%s: (%s', field, type) - else - text = string.format('(%s', type) - end - else - text = string.format('"%s"', type:gsub('\n', '\\n'):gsub('"', '\\"')) - end - table.insert(tree, { - id = child:id(), - text = text, - named = named, + node = child, + field = field, depth = depth, - lnum = lnum, - col = col, - end_lnum = end_lnum, - end_col = end_col, lang = lang, }) traverse(child, depth + 1, lang, injections, tree) - - if named then - tree[#tree].text = string.format('%s)', tree[#tree].text) - end end return tree @@ -132,7 +105,7 @@ function TSTreeView:new(bufnr, lang) local named = {} ---@type TSP.Node[] for _, v in ipairs(nodes) do - if v.named then + if v.node:named() then named[#named + 1] = v end end @@ -213,7 +186,7 @@ local function set_inspector_cursor(treeview, lang, source_buf, inspect_buf, ins local cursor_node_id = cursor_node:id() for i, v in treeview:iter() do - if v.id == cursor_node_id then + if v.node:id() == cursor_node_id then local start = v.depth * treeview.opts.indent ---@type integer local end_col = start + #v.text api.nvim_buf_set_extmark(inspect_buf, treeview.ns, i - 1, start, { @@ -228,6 +201,8 @@ end --- Write the contents of this View into {bufnr}. --- +--- Calling this function computes the text that is displayed for each node. +--- ---@param bufnr integer Buffer number to write into. ---@package function TSTreeView:draw(bufnr) @@ -235,13 +210,35 @@ function TSTreeView:draw(bufnr) local lines = {} ---@type string[] local lang_hl_marks = {} ---@type table[] - for _, item in self:iter() do - local range_str = get_range_str(item.lnum, item.col, item.end_lnum, item.end_col) + for i, item in self:iter() do + local range_str = get_range_str(item.node:range()) local lang_str = self.opts.lang and string.format(' %s', item.lang) or '' + + local text ---@type string + if item.node:named() then + if item.field then + text = string.format('%s: (%s', item.field, item.node:type()) + else + text = string.format('(%s', item.node:type()) + end + else + text = string.format('"%s"', item.node:type():gsub('\n', '\\n'):gsub('"', '\\"')) + end + + local next = self:get(i + 1) + if not next or next.depth <= item.depth then + local parens = item.depth - (next and next.depth or 0) + (item.node:named() and 1 or 0) + if parens > 0 then + text = string.format('%s%s', text, string.rep(')', parens)) + end + end + + item.text = text + local line = string.format( '%s%s ; %s%s', string.rep(' ', item.depth * self.opts.indent), - item.text, + text, range_str, lang_str ) @@ -253,7 +250,7 @@ function TSTreeView:draw(bufnr) } end - lines[#lines + 1] = line + lines[i] = line end api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) @@ -364,9 +361,9 @@ function M.inspect_tree(opts) desc = 'Jump to the node under the cursor in the source buffer', callback = function() local row = api.nvim_win_get_cursor(w)[1] - local pos = treeview:get(row) + local lnum, col = treeview:get(row).node:start() api.nvim_set_current_win(win) - api.nvim_win_set_cursor(win, { pos.lnum + 1, pos.col }) + api.nvim_win_set_cursor(win, { lnum + 1, col }) end, }) api.nvim_buf_set_keymap(b, 'n', 'a', '', { @@ -374,7 +371,7 @@ function M.inspect_tree(opts) callback = function() local row, col = unpack(api.nvim_win_get_cursor(w)) ---@type integer, integer local curnode = treeview:get(row) - while curnode and not curnode.named do + while curnode and not curnode.node:named() do row = row - 1 curnode = treeview:get(row) end @@ -386,9 +383,9 @@ function M.inspect_tree(opts) return end - local id = curnode.id + local id = curnode.node:id() for i, node in treeview:iter() do - if node.id == id then + if node.node:id() == id then api.nvim_win_set_cursor(w, { i, col }) break end @@ -424,20 +421,20 @@ function M.inspect_tree(opts) api.nvim_buf_clear_namespace(buf, treeview.ns, 0, -1) local row = api.nvim_win_get_cursor(w)[1] - local pos = treeview:get(row) - api.nvim_buf_set_extmark(buf, treeview.ns, pos.lnum, pos.col, { - end_row = pos.end_lnum, - end_col = math.max(0, pos.end_col), + local lnum, col, end_lnum, end_col = treeview:get(row).node:range() + api.nvim_buf_set_extmark(buf, treeview.ns, lnum, col, { + end_row = end_lnum, + end_col = math.max(0, end_col), hl_group = 'Visual', }) local topline, botline = vim.fn.line('w0', win), vim.fn.line('w$', win) -- Move the cursor if highlighted range is completely out of view - if pos.lnum < topline and pos.end_lnum < topline then - api.nvim_win_set_cursor(win, { pos.end_lnum + 1, 0 }) - elseif pos.lnum > botline and pos.end_lnum > botline then - api.nvim_win_set_cursor(win, { pos.lnum + 1, 0 }) + if lnum < topline and end_lnum < topline then + api.nvim_win_set_cursor(win, { end_lnum + 1, 0 }) + elseif lnum > botline and end_lnum > botline then + api.nvim_win_set_cursor(win, { lnum + 1, 0 }) end end, }) -- cgit From f5573fba3d460ddf479826b7404e568cc825ed57 Mon Sep 17 00:00:00 2001 From: Pham Huy Hoang Date: Fri, 1 Dec 2023 01:37:42 +0900 Subject: fix: Remove nested for_each_tree in TSTreeView (#26328) Problem: `LanguageTree:for_each_tree` calls itself for child nodes, so when we calls `for_each_tree` inside `for_each_tree`, this quickly leads to exponential tree calls. Solution: Use `pairs(child:trees())` directly in this case, as we don't need the extra callback for each children, this is already handled from the outer `for_each_tree` call --- runtime/lua/vim/treesitter/dev.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index aad639d85a..870761b7c7 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -87,17 +87,17 @@ function TSTreeView:new(bufnr, lang) parser:for_each_tree(function(parent_tree, parent_ltree) local parent = parent_tree:root() for _, child in pairs(parent_ltree:children()) do - child:for_each_tree(function(tree, ltree) + for _, tree in pairs(child:trees()) do local r = tree:root() local node = assert(parent:named_descendant_for_range(r:range())) local id = node:id() if not injections[id] or r:byte_length() > injections[id].root:byte_length() then injections[id] = { - lang = ltree:lang(), + lang = child:lang(), root = r, } end - end) + end end end) -- cgit From 307d5bcc7940d14f7d17e7c2de795ebed7b0f00c Mon Sep 17 00:00:00 2001 From: ObserverOfTime Date: Thu, 30 Nov 2023 19:00:33 +0200 Subject: vim-patch:9.0.2137: Can't detect angular & mustache filetypes Problem: Can't detect angular & mustache filetypes Solution: Detect *.mustache as Mustache filetype; detect *.component.html as html.angular filetype closes: vim/vim#13594 https://github.com/vim/vim/commit/7bed263c343c62129c5d8f51796895a28db1b312 --- runtime/lua/vim/filetype.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index c6200f16bb..2bbc545fc4 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -695,6 +695,7 @@ local extension = { msql = 'msql', mu = 'mupad', mush = 'mush', + mustache = 'mustache', mysql = 'mysql', n1ql = 'n1ql', nql = 'n1ql', @@ -1716,6 +1717,7 @@ local pattern = { ['.*/etc/host%.conf'] = 'hostconf', ['.*/etc/hosts%.deny'] = 'hostsaccess', ['.*/etc/hosts%.allow'] = 'hostsaccess', + ['.*%.component%.html'] = 'html.angular', ['.*%.html%.m4'] = 'htmlm4', ['.*/%.i3/config'] = 'i3config', ['.*/i3/config'] = 'i3config', -- cgit From b32b5b2711ed338f4944c983a247f80c3163f87c Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:17:38 -0600 Subject: fix: use BEL to terminate OSC 11 request (#26335) --- runtime/lua/vim/_defaults.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index cc872dea83..c3bb36fc36 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -297,7 +297,7 @@ do end, }) - io.stdout:write('\027]11;?\027\\') + io.stdout:write('\027]11;?\007') timer:start(1000, 0, function() -- No response received. Delete the autocommand -- cgit From fedbf32250ba303ee06c751e798c28c5a3f05862 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 2 Dec 2023 09:42:16 +0800 Subject: vim-patch:9.0.2139: html.angular ft is problematic (#26357) Problem: html.angular ft is problematic Solution: partly revert v9.0.2137 The html.angular filetype causes issues and does not trigger FileType autocommands for the html or angular filetypes. So let's roll back that particular change and detect this only as html file related: https://github.com/vim/vim/pull/13594#issuecomment-1834465890 closes: vim/vim#13604 https://github.com/vim/vim/commit/4f3480c94358e3b938594fc3574477e780525cd7 Co-authored-by: Christian Brabandt --- runtime/lua/vim/filetype.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 2bbc545fc4..60882d4432 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1717,7 +1717,6 @@ local pattern = { ['.*/etc/host%.conf'] = 'hostconf', ['.*/etc/hosts%.deny'] = 'hostsaccess', ['.*/etc/hosts%.allow'] = 'hostsaccess', - ['.*%.component%.html'] = 'html.angular', ['.*%.html%.m4'] = 'htmlm4', ['.*/%.i3/config'] = 'i3config', ['.*/i3/config'] = 'i3config', -- cgit From cf612c64b0fc87c399bc5c72735335c5e73d6de1 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Mon, 4 Dec 2023 04:00:49 -0500 Subject: fix(treesitter): allow passing lang to vim.treesitter.get_node() now correctly takes opts.lang (#26360) PROBLEM: `vim.treesitter.get_node()` does not recognize the `lang` in the option table. This option was used in somewhere else, for instance, `vim.treesitter.dev` (for `inspect_tree`) but was never implemented. SOLUTION: Make `get_node()` correctly use `opts.lang` when getting a treesitter parser. --- runtime/lua/vim/treesitter.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index e7a66c00b2..7b795380fe 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -362,6 +362,7 @@ end --- - bufnr integer|nil Buffer number (nil or 0 for current buffer) --- - pos table|nil 0-indexed (row, col) tuple. Defaults to cursor position in the --- current window. Required if {bufnr} is not the current buffer +--- - lang string|nil Parser language. (default: from buffer filetype) --- - ignore_injections boolean Ignore injected languages (default true) --- ---@return TSNode | nil Node at the given position @@ -392,7 +393,7 @@ function M.get_node(opts) local ts_range = { row, col, row, col } - local root_lang_tree = M.get_parser(bufnr) + local root_lang_tree = M.get_parser(bufnr, opts.lang) if not root_lang_tree then return end -- cgit From c9828200ac99c0f0769c587ddc060045ab3a9ad5 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 5 Dec 2023 09:24:28 +0100 Subject: vim-patch:9.0.2148: Vim does not detect pacman.log file Problem: Vim does not detect pacman.log file Solution: Detect pacmanlogs and add syntax highlighting pacman.log is a filetype common to Arch Liux and related distributions. Add some simple syntax highlighting for the pacmanlog filetype. closes: vim/vim#13618 https://github.com/vim/vim/commit/1e5d66408ef85c750a5af03bbf5cc19b5de7a6bc Co-authored-by: Ronan Pigott --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 60882d4432..e64923ab54 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1394,6 +1394,7 @@ local filename = { octaverc = 'octave', ['octave.conf'] = 'octave', opam = 'opam', + ['pacman.log'] = 'pacmanlog', ['/etc/pam.conf'] = 'pamconf', ['pam_env.conf'] = 'pamenv', ['.pam_environment'] = 'pamenv', -- cgit From 0b74ad0a641f28d9d3da5353e98372d87078bd9d Mon Sep 17 00:00:00 2001 From: Riccardo Mazzarini Date: Tue, 5 Dec 2023 12:33:57 +0100 Subject: refactor(api): complete conversion from `Dictionary` to `Dict(opts)` (#26365) --- runtime/lua/vim/_meta/api.lua | 20 ++++++++++---------- runtime/lua/vim/_meta/api_keysets.lua | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 10 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 49269ba631..4ad0a2e791 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -151,7 +151,7 @@ function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start --- `nvim_buf_lines_event`. Else the first notification --- will be `nvim_buf_changedtick_event`. Not for Lua --- callbacks. ---- @param opts table Optional parameters. +--- @param opts vim.api.keyset.buf_attach Optional parameters. --- • on_lines: Lua callback invoked on change. Return `true` to detach. Args: --- • the string "lines" --- • buffer handle @@ -284,7 +284,7 @@ function vim.api.nvim_buf_del_var(buffer, name) end --- Deletes the buffer. See `:bwipeout` --- --- @param buffer integer Buffer handle, or 0 for current buffer ---- @param opts table Optional parameters. Keys: +--- @param opts vim.api.keyset.buf_delete Optional parameters. Keys: --- • force: Force deletion and ignore unsaved changes. --- • unload: Unloaded only, do not delete. See `:bunload` function vim.api.nvim_buf_delete(buffer, opts) end @@ -307,7 +307,7 @@ function vim.api.nvim_buf_get_commands(buffer, opts) end --- @param buffer integer Buffer handle, or 0 for current buffer --- @param ns_id integer Namespace id from `nvim_create_namespace()` --- @param id integer Extmark id ---- @param opts table Optional parameters. Keys: +--- @param opts vim.api.keyset.get_extmark Optional parameters. Keys: --- • details: Whether to include the details dict --- • hl_name: Whether to include highlight group name instead --- of id, true if omitted @@ -440,7 +440,7 @@ function vim.api.nvim_buf_get_option(buffer, name) end --- @param start_col integer Starting column (byte offset) on first line --- @param end_row integer Last line index, inclusive --- @param end_col integer Ending column (byte offset) on last line, exclusive ---- @param opts table Optional parameters. Currently unused. +--- @param opts vim.api.keyset.empty Optional parameters. Currently unused. --- @return string[] function vim.api.nvim_buf_get_text(buffer, start_row, start_col, end_row, end_col, opts) end @@ -626,7 +626,7 @@ function vim.api.nvim_buf_set_lines(buffer, start, end_, strict_indexing, replac --- @param name string Mark name --- @param line integer Line number --- @param col integer Column/row number ---- @param opts table Optional parameters. Reserved for future use. +--- @param opts vim.api.keyset.empty Optional parameters. Reserved for future use. --- @return boolean function vim.api.nvim_buf_set_mark(buffer, name, line, col, opts) end @@ -675,7 +675,7 @@ function vim.api.nvim_buf_set_var(buffer, name, value) end --- @param src_id integer --- @param line integer --- @param chunks any[] ---- @param opts table +--- @param opts vim.api.keyset.empty --- @return integer function vim.api.nvim_buf_set_virtual_text(buffer, src_id, line, chunks, opts) end @@ -1241,7 +1241,7 @@ function vim.api.nvim_get_keymap(mode) end --- Marks are (1,0)-indexed. `api-indexing` --- --- @param name string Mark name ---- @param opts table Optional parameters. Reserved for future use. +--- @param opts vim.api.keyset.empty Optional parameters. Reserved for future use. --- @return any[] function vim.api.nvim_get_mark(name, opts) end @@ -1439,7 +1439,7 @@ function vim.api.nvim_notify(msg, log_level, opts) end --- virtual terminal having the intended size. --- --- @param buffer integer the buffer to use (expected to be empty) ---- @param opts table Optional parameters. +--- @param opts vim.api.keyset.open_term Optional parameters. --- • on_input: Lua callback for input sent, i e keypresses in --- terminal mode. Note: keypresses are sent raw as they would --- be to the pty master end. For instance, a carriage return @@ -1602,7 +1602,7 @@ function vim.api.nvim_out_write(str) end --- Doesn't check the validity of command arguments. --- --- @param str string Command line string to parse. Cannot contain "\n". ---- @param opts table Optional parameters. Reserved for future use. +--- @param opts vim.api.keyset.empty Optional parameters. Reserved for future use. --- @return table function vim.api.nvim_parse_cmd(str, opts) end @@ -1685,7 +1685,7 @@ function vim.api.nvim_replace_termcodes(str, from_part, do_lt, special) end --- inserted in the buffer. Ignored for `cmdline-completion`. --- @param finish boolean Finish the completion and dismiss the popup menu. Implies --- {insert}. ---- @param opts table Optional parameters. Reserved for future use. +--- @param opts vim.api.keyset.empty Optional parameters. Reserved for future use. function vim.api.nvim_select_popupmenu_item(item, insert, finish, opts) end --- Sets the current buffer. diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index f69e5a92c7..6a3e574455 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -3,6 +3,19 @@ -- DO NOT EDIT error('Cannot require a meta file') +--- @class vim.api.keyset.buf_attach +--- @field on_lines? function +--- @field on_bytes? function +--- @field on_changedtick? function +--- @field on_detach? function +--- @field on_reload? function +--- @field utf_sizes? boolean +--- @field preview? boolean + +--- @class vim.api.keyset.buf_delete +--- @field force? boolean +--- @field unload? boolean + --- @class vim.api.keyset.clear_autocmds --- @field buffer? integer --- @field event? any @@ -74,6 +87,8 @@ error('Cannot require a meta file') --- @class vim.api.keyset.echo_opts --- @field verbose? boolean +--- @class vim.api.keyset.empty + --- @class vim.api.keyset.eval_statusline --- @field winid? integer --- @field maxwidth? integer @@ -124,6 +139,10 @@ error('Cannot require a meta file') --- @class vim.api.keyset.get_commands --- @field builtin? boolean +--- @class vim.api.keyset.get_extmark +--- @field details? boolean +--- @field hl_name? boolean + --- @class vim.api.keyset.get_extmarks --- @field limit? integer --- @field details? boolean @@ -196,6 +215,9 @@ error('Cannot require a meta file') --- @field desc? string --- @field replace_keycodes? boolean +--- @class vim.api.keyset.open_term +--- @field on_input? function + --- @class vim.api.keyset.option --- @field scope? string --- @field win? integer -- cgit From 5b40a1c09dda83275784053b325ad16626fc55f2 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Tue, 5 Dec 2023 18:35:22 -0800 Subject: feat(lua): implement Iter:join() (#26416) --- runtime/lua/vim/iter.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index 874bdfb437..e9c2b66bf2 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -356,6 +356,18 @@ function ListIter.totable(self) return self._table end +--- Collect the iterator into a delimited string. +--- +--- Each element in the iterator is joined into a string separated by {delim}. +--- +--- Consumes the iterator. +--- +--- @param delim string Delimiter +--- @return string +function Iter.join(self, delim) + return table.concat(self:totable(), delim) +end + --- Folds ("reduces") an iterator into a single value. --- --- Examples: -- cgit From e057b38e7037808b3593fb1035794595b4e4a45e Mon Sep 17 00:00:00 2001 From: Emanuel Date: Wed, 6 Dec 2023 16:56:04 +0100 Subject: fix(json): allow objects with empty keys #25564 Problem: Empty string is a valid JSON key, but json_decode() treats an object with empty key as ":help msgpack-special-dict". #20757 :echo json_decode('{"": "1"}') {'_TYPE': [], '_VAL': [['', '1']]} Note: vim returns `{'': '1'}`. Solution: Allow empty string as an object key. Note that we still (currently) disallow empty keys in object_to_vim() (since 7c01d5ff9286d262097484c680e3a4eab49e2911): https://github.com/neovim/neovim/blob/f64e4b43e1191ff30d902730f752875aa55682ce/src/nvim/api/private/converter.c#L333-L334 Fix #20757 Co-authored-by: Justin M. Keyes --- runtime/lua/vim/_meta/vimfn.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 05e5b2b871..7234b813b6 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -4678,8 +4678,7 @@ function vim.fn.join(list, sep) end --- Vim value. In the following cases it will output --- |msgpack-special-dict|: --- 1. Dictionary contains duplicate key. ---- 2. Dictionary contains empty key. ---- 3. String contains NUL byte. Two special dictionaries: for +--- 2. String contains NUL byte. Two special dictionaries: for --- dictionary and for string will be emitted in case string --- with NUL byte was a dictionary key. --- @@ -5922,7 +5921,6 @@ function vim.fn.msgpackdump(list, type) end --- are binary strings). --- 2. String with NUL byte inside. --- 3. Duplicate key. ---- 4. Empty key. --- ext |List| with two values: first is a signed integer --- representing extension type. Second is --- |readfile()|-style list of strings. -- cgit From 2613ba5000d4c0d9b15e2eec2d2b97615575925e Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Tue, 5 Dec 2023 10:01:32 -0800 Subject: feat(defaults): enable 'termguicolors' by default when supported by terminal Enable 'termguicolors' automatically when Nvim can detect that truecolor is supported by the host terminal. If $COLORTERM is set to "truecolor" or "24bit", or the terminal's terminfo entry contains capabilities for Tc, RGB, or setrgbf and setrgbb, then we assume that the terminal supports truecolor. Otherwise, the terminal is queried (using both XTGETTCAP and SGR + DECRQSS). If the terminal's response to these queries (if any) indicates that it supports truecolor, then 'termguicolors' is enabled. --- runtime/lua/vim/_defaults.lua | 255 +++++++++++++++++++++++++++----------- runtime/lua/vim/_meta.lua | 1 + runtime/lua/vim/_meta/options.lua | 4 + runtime/lua/vim/termcap.lua | 52 ++++++-- 4 files changed, 227 insertions(+), 85 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index c3bb36fc36..b73681be04 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -165,91 +165,92 @@ do }) end ---- Guess value of 'background' based on terminal color. ---- ---- We write Operating System Command (OSC) 11 to the terminal to request the ---- terminal's background color. We then wait for a response. If the response ---- matches `rgba:RRRR/GGGG/BBBB/AAAA` where R, G, B, and A are hex digits, then ---- compute the luminance[1] of the RGB color and classify it as light/dark ---- accordingly. Note that the color components may have anywhere from one to ---- four hex digits, and require scaling accordingly as values out of 4, 8, 12, ---- or 16 bits. Also note the A(lpha) component is optional, and is parsed but ---- ignored in the calculations. ---- ---- [1] https://en.wikipedia.org/wiki/Luma_%28video%29 -do - --- Parse a string of hex characters as a color. - --- - --- The string can contain 1 to 4 hex characters. The returned value is - --- between 0.0 and 1.0 (inclusive) representing the intensity of the color. - --- - --- For instance, if only a single hex char "a" is used, then this function - --- returns 0.625 (10 / 16), while a value of "aa" would return 0.664 (170 / - --- 256). - --- - --- @param c string Color as a string of hex chars - --- @return number? Intensity of the color - local function parsecolor(c) - if #c == 0 or #c > 4 then - return nil - end - - local val = tonumber(c, 16) - if not val then - return nil - end - - local max = tonumber(string.rep('f', #c), 16) - return val / max +-- Only do the following when the TUI is attached +local tty = nil +for _, ui in ipairs(vim.api.nvim_list_uis()) do + if ui.chan == 1 and ui.stdout_tty then + tty = ui + break end +end - --- Parse an OSC 11 response - --- - --- Either of the two formats below are accepted: - --- - --- OSC 11 ; rgb:// - --- - --- or - --- - --- OSC 11 ; rgba:/// +if tty then + --- Guess value of 'background' based on terminal color. --- - --- where + --- We write Operating System Command (OSC) 11 to the terminal to request the + --- terminal's background color. We then wait for a response. If the response + --- matches `rgba:RRRR/GGGG/BBBB/AAAA` where R, G, B, and A are hex digits, then + --- compute the luminance[1] of the RGB color and classify it as light/dark + --- accordingly. Note that the color components may have anywhere from one to + --- four hex digits, and require scaling accordingly as values out of 4, 8, 12, + --- or 16 bits. Also note the A(lpha) component is optional, and is parsed but + --- ignored in the calculations. --- - --- , , , := h | hh | hhh | hhhh - --- - --- The alpha component is ignored, if present. - --- - --- @param resp string OSC 11 response - --- @return string? Red component - --- @return string? Green component - --- @return string? Blue component - local function parseosc11(resp) - local r, g, b - r, g, b = resp:match('^\027%]11;rgb:(%x+)/(%x+)/(%x+)$') - if not r and not g and not b then - local a - r, g, b, a = resp:match('^\027%]11;rgba:(%x+)/(%x+)/(%x+)/(%x+)$') - if not a or #a > 4 then - return nil, nil, nil + --- [1] https://en.wikipedia.org/wiki/Luma_%28video%29 + do + --- Parse a string of hex characters as a color. + --- + --- The string can contain 1 to 4 hex characters. The returned value is + --- between 0.0 and 1.0 (inclusive) representing the intensity of the color. + --- + --- For instance, if only a single hex char "a" is used, then this function + --- returns 0.625 (10 / 16), while a value of "aa" would return 0.664 (170 / + --- 256). + --- + --- @param c string Color as a string of hex chars + --- @return number? Intensity of the color + local function parsecolor(c) + if #c == 0 or #c > 4 then + return nil end - end - if r and g and b and #r <= 4 and #g <= 4 and #b <= 4 then - return r, g, b + local val = tonumber(c, 16) + if not val then + return nil + end + + local max = tonumber(string.rep('f', #c), 16) + return val / max end - return nil, nil, nil - end + --- Parse an OSC 11 response + --- + --- Either of the two formats below are accepted: + --- + --- OSC 11 ; rgb:// + --- + --- or + --- + --- OSC 11 ; rgba:/// + --- + --- where + --- + --- , , , := h | hh | hhh | hhhh + --- + --- The alpha component is ignored, if present. + --- + --- @param resp string OSC 11 response + --- @return string? Red component + --- @return string? Green component + --- @return string? Blue component + local function parseosc11(resp) + local r, g, b + r, g, b = resp:match('^\027%]11;rgb:(%x+)/(%x+)/(%x+)$') + if not r and not g and not b then + local a + r, g, b, a = resp:match('^\027%]11;rgba:(%x+)/(%x+)/(%x+)/(%x+)$') + if not a or #a > 4 then + return nil, nil, nil + end + end + + if r and g and b and #r <= 4 and #g <= 4 and #b <= 4 then + return r, g, b + end - local tty = false - for _, ui in ipairs(vim.api.nvim_list_uis()) do - if ui.chan == 1 and ui.stdout_tty then - tty = true - break + return nil, nil, nil end - end - if tty then local timer = assert(vim.uv.new_timer()) ---@param bg string New value of the 'background' option @@ -300,7 +301,7 @@ do io.stdout:write('\027]11;?\007') timer:start(1000, 0, function() - -- No response received. Delete the autocommand + -- Delete the autocommand if no response was received vim.schedule(function() -- Suppress error if autocommand has already been deleted pcall(vim.api.nvim_del_autocmd, id) @@ -311,4 +312,108 @@ do end end) end + + --- If the TUI (term_has_truecolor) was able to determine that the host + --- terminal supports truecolor, enable 'termguicolors'. Otherwise, query the + --- terminal (using both XTGETTCAP and SGR + DECRQSS). If the terminal's + --- response indicates that it does support truecolor enable 'termguicolors', + --- but only if the user has not already disabled it. + do + if tty.rgb then + -- The TUI was able to determine truecolor support + vim.o.termguicolors = true + else + --- Enable 'termguicolors', but only if it was not already set by the user. + local function settgc() + if not vim.api.nvim_get_option_info2('termguicolors', {}).was_set then + vim.o.termguicolors = true + end + end + + local caps = {} ---@type table + require('vim.termcap').query({ 'Tc', 'RGB', 'setrgbf', 'setrgbb' }, function(cap, found) + if not found then + return + end + + caps[cap] = true + if caps.Tc or caps.RGB or (caps.setrgbf and caps.setrgbb) then + settgc() + end + end) + + local timer = assert(vim.uv.new_timer()) + + -- Arbitrary colors to set in the SGR sequence + local r = 1 + local g = 2 + local b = 3 + + local id = vim.api.nvim_create_autocmd('TermResponse', { + nested = true, + callback = function(args) + local resp = args.data ---@type string + local decrqss = resp:match('^\027P1%$r([%d;:]+)m$') + + if decrqss then + -- The DECRQSS SGR response first contains attributes separated by + -- semicolons, followed by the SGR itself with parameters separated + -- by colons. Some terminals include "0" in the attribute list + -- unconditionally; others do not. Our SGR sequence did not set any + -- attributes, so there should be no attributes in the list. + local attrs = vim.split(decrqss, ';') + if #attrs ~= 1 and (#attrs ~= 2 or attrs[1] ~= '0') then + return true + end + + -- The returned SGR sequence should begin with 48:2 + local sgr = attrs[#attrs]:match('^48:2:([%d:]+)$') + if not sgr then + return true + end + + -- The remaining elements of the SGR sequence should be the 3 colors + -- we set. Some terminals also include an additional parameter + -- (which can even be empty!), so handle those cases as well + local params = vim.split(sgr, ':') + if #params ~= 3 and (#params ~= 4 or (params[1] ~= '' and params[1] ~= '1')) then + return true + end + + if + tonumber(params[#params - 2]) == r + and tonumber(params[#params - 1]) == g + and tonumber(params[#params]) == b + then + settgc() + end + + return true + end + end, + }) + + -- Write SGR followed by DECRQSS. This sets the background color then + -- immediately asks the terminal what the background color is. If the + -- terminal responds to the DECRQSS with the same SGR sequence that we + -- sent then the terminal supports truecolor. + local decrqss = '\027P$qm\027\\' + if os.getenv('TMUX') then + decrqss = string.format('\027Ptmux;%s\027\\', decrqss:gsub('\027', '\027\027')) + end + io.stdout:write(string.format('\027[48;2;%d;%d;%dm%s', r, g, b, decrqss)) + + timer:start(1000, 0, function() + -- Delete the autocommand if no response was received + vim.schedule(function() + -- Suppress error if autocommand has already been deleted + pcall(vim.api.nvim_del_autocmd, id) + end) + + if not timer:is_closing() then + timer:close() + end + end) + end + end end diff --git a/runtime/lua/vim/_meta.lua b/runtime/lua/vim/_meta.lua index e3b99f6b3d..bb9ed722e2 100644 --- a/runtime/lua/vim/_meta.lua +++ b/runtime/lua/vim/_meta.lua @@ -20,6 +20,7 @@ vim.lsp = require('vim.lsp') vim.re = require('vim.re') vim.secure = require('vim.secure') vim.snippet = require('vim.snippet') +vim.text = require('vim.text') vim.treesitter = require('vim.treesitter') vim.ui = require('vim.ui') vim.version = require('vim.version') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index d2bdab4d28..5e65ca6b1b 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -6941,6 +6941,10 @@ vim.go.tbidi = vim.go.termbidi --- attributes instead of "cterm" attributes. `guifg` --- Requires an ISO-8613-3 compatible terminal. --- +--- Nvim will automatically attempt to determine if the host terminal +--- supports 24-bit color and will enable this option if it does +--- (unless explicitly disabled by the user). +--- --- @type boolean vim.o.termguicolors = false vim.o.tgc = vim.o.termguicolors diff --git a/runtime/lua/vim/termcap.lua b/runtime/lua/vim/termcap.lua index 862cc52149..b88d9ac9ba 100644 --- a/runtime/lua/vim/termcap.lua +++ b/runtime/lua/vim/termcap.lua @@ -12,7 +12,10 @@ local M = {} --- emulator supports the XTGETTCAP sequence. --- --- @param caps string|table A terminal capability or list of capabilities to query ---- @param cb function(cap:string, seq:string) Function to call when a response is received +--- @param cb function(cap:string, found:bool, seq:string?) Callback function which is called for +--- each capability in {caps}. {found} is set to true if the capability was found or false +--- otherwise. {seq} is the control sequence for the capability if found, or nil for +--- boolean capabilities. function M.query(caps, cb) vim.validate({ caps = { caps, { 'string', 'table' } }, @@ -23,21 +26,33 @@ function M.query(caps, cb) caps = { caps } end - local count = #caps + local pending = {} ---@type table + for _, v in ipairs(caps) do + pending[v] = true + end + + local timer = assert(vim.uv.new_timer()) - vim.api.nvim_create_autocmd('TermResponse', { + local id = vim.api.nvim_create_autocmd('TermResponse', { callback = function(args) local resp = args.data ---@type string - local k, v = resp:match('^\027P1%+r(%x+)=(%x+)$') - if k and v then + local k, rest = resp:match('^\027P1%+r(%x+)(.*)$') + if k and rest then local cap = vim.text.hexdecode(k) - local seq = - vim.text.hexdecode(v):gsub('\\E', '\027'):gsub('%%p%d', ''):gsub('\\(%d+)', string.char) + local seq ---@type string? + if rest:match('^=%x+$') then + seq = vim.text + .hexdecode(rest:sub(2)) + :gsub('\\E', '\027') + :gsub('%%p%d', '') + :gsub('\\(%d+)', string.char) + end + + cb(cap, true, seq) - cb(cap, seq) + pending[cap] = nil - count = count - 1 - if count == 0 then + if next(pending) == nil then return true end end @@ -57,6 +72,23 @@ function M.query(caps, cb) end io.stdout:write(query) + + timer:start(1000, 0, function() + -- Delete the autocommand if no response was received + vim.schedule(function() + -- Suppress error if autocommand has already been deleted + pcall(vim.api.nvim_del_autocmd, id) + + -- Call the callback for all capabilities that were not found + for k in pairs(pending) do + cb(k, false, nil) + end + end) + + if not timer:is_closing() then + timer:close() + end + end) end return M -- cgit From a1bdf2852d6d848e5b4522f9a66d53e9296c1872 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Fri, 8 Dec 2023 12:23:46 -0800 Subject: fix(snippet): remove misleading comment about TM_FILENAME_BASE (#26465) --- runtime/lua/vim/snippet.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua index 32a8ea0b0d..ac25fb6a2d 100644 --- a/runtime/lua/vim/snippet.lua +++ b/runtime/lua/vim/snippet.lua @@ -42,9 +42,7 @@ local function resolve_variable(var, default) elseif var == 'TM_FILENAME' then return expand_or_default('%:t') elseif var == 'TM_FILENAME_BASE' then - -- Not using '%:t:r' since we want to remove all extensions. - local filename_base = expand_or_default('%:t'):gsub('%.[^%.]*$', '') - return filename_base + return expand_or_default('%:t:r') elseif var == 'TM_DIRECTORY' then return expand_or_default('%:p:h:t') elseif var == 'TM_FILEPATH' then -- cgit From 3692fd4c873a2cd7ad69eb09765eed2993570c49 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Mon, 11 Dec 2023 04:10:00 -0500 Subject: feat(gen_lsp.lua): validate CLI args #26514 - Improve CLI argument parsing, rejects invalid argument and commands as early as possible. Also prints USAGE in the command line. - No longer allows `--`, use `--out ` instead. - Print a little bit of verbose messages to better know what's going on rather than remaining silent at all times. - Add type annotation `gen_lsp._opt` to avoid type warnings. --- runtime/lua/vim/lsp/_meta/protocol.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/_meta/protocol.lua b/runtime/lua/vim/lsp/_meta/protocol.lua index 72b0f00f65..979dad84fd 100644 --- a/runtime/lua/vim/lsp/_meta/protocol.lua +++ b/runtime/lua/vim/lsp/_meta/protocol.lua @@ -1,7 +1,7 @@ --[[ This file is autogenerated from scripts/gen_lsp.lua Regenerate: -nvim -l scripts/gen_lsp.lua gen --version 3.18 --runtime/lua/vim/lsp/_meta/protocol.lua +nvim -l scripts/gen_lsp.lua gen --version 3.18 --out runtime/lua/vim/lsp/_meta/protocol.lua --]] ---@meta -- cgit From 7c6f9690f74eea5ae922f1d0db808de61ef61ab0 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Sat, 9 Dec 2023 15:21:08 +0900 Subject: fix(treesitter): fix indexing in foldexpr --- runtime/lua/vim/treesitter/_fold.lua | 43 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 21 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua index 5c1cc06908..d5626d0391 100644 --- a/runtime/lua/vim/treesitter/_fold.lua +++ b/runtime/lua/vim/treesitter/_fold.lua @@ -5,8 +5,8 @@ local Range = require('vim.treesitter._range') local api = vim.api ---@class TS.FoldInfo ----@field levels table ----@field levels0 table +---@field levels string[] the foldexpr value for each line +---@field levels0 integer[] the raw fold levels ---@field private start_counts table ---@field private stop_counts table local FoldInfo = {} @@ -24,13 +24,13 @@ end ---@package ---@param srow integer ----@param erow integer +---@param erow integer 0-indexed, exclusive function FoldInfo:invalidate_range(srow, erow) - for i = srow, erow do - self.start_counts[i + 1] = nil - self.stop_counts[i + 1] = nil - self.levels0[i + 1] = nil - self.levels[i + 1] = nil + for i = srow + 1, erow do + self.start_counts[i] = nil + self.stop_counts[i] = nil + self.levels0[i] = nil + self.levels[i] = nil end end @@ -55,7 +55,7 @@ end ---@package ---@param srow integer ----@param erow integer +---@param erow integer 0-indexed, exclusive function FoldInfo:remove_range(srow, erow) list_remove(self.levels, srow + 1, erow) list_remove(self.levels0, srow + 1, erow) @@ -91,7 +91,7 @@ end ---@package ---@param srow integer ----@param erow integer +---@param erow integer 0-indexed, exclusive function FoldInfo:add_range(srow, erow) list_insert(self.levels, srow + 1, erow, '-1') list_insert(self.levels0, srow + 1, erow, -1) @@ -140,10 +140,10 @@ end --- TODO(lewis6991): Handle this generally --- --- @param bufnr integer ---- @param erow integer? +--- @param erow integer? 0-indexed, exclusive --- @return integer local function normalise_erow(bufnr, erow) - local max_erow = api.nvim_buf_line_count(bufnr) - 1 + local max_erow = api.nvim_buf_line_count(bufnr) return math.min(erow or max_erow, max_erow) end @@ -152,7 +152,7 @@ end ---@param bufnr integer ---@param info TS.FoldInfo ---@param srow integer? ----@param erow integer? +---@param erow integer? 0-indexed, exclusive ---@param parse_injections? boolean local function get_folds_levels(bufnr, info, srow, erow, parse_injections) srow = srow or 0 @@ -173,10 +173,7 @@ local function get_folds_levels(bufnr, info, srow, erow, parse_injections) return end - -- erow in query is end-exclusive - local q_erow = erow and erow + 1 or -1 - - for id, node, metadata in query:iter_captures(tree:root(), bufnr, srow, q_erow) do + for id, node, metadata in query:iter_captures(tree:root(), bufnr, srow, erow) do if query.captures[id] == 'fold' then local range = ts.get_range(node, bufnr, metadata[id]) local start, _, stop, stop_col = Range.unpack4(range) @@ -205,7 +202,7 @@ local function get_folds_levels(bufnr, info, srow, erow, parse_injections) local current_level = info.levels0[srow] or 0 -- We now have the list of fold opening and closing, fill the gaps and mark where fold start - for lnum = srow + 1, erow + 1 do + for lnum = srow + 1, erow do local last_trimmed_level = trim_level(current_level) current_level = current_level + info:get_start(lnum) info.levels0[lnum] = current_level @@ -296,7 +293,10 @@ end local function on_changedtree(bufnr, foldinfo, tree_changes) schedule_if_loaded(bufnr, function() for _, change in ipairs(tree_changes) do - local srow, _, erow = Range.unpack4(change) + local srow, _, erow, ecol = Range.unpack4(change) + if ecol > 0 then + erow = erow + 1 + end get_folds_levels(bufnr, foldinfo, srow, erow) end if #tree_changes > 0 then @@ -311,8 +311,9 @@ end ---@param old_row integer ---@param new_row integer local function on_bytes(bufnr, foldinfo, start_row, old_row, new_row) - local end_row_old = start_row + old_row - local end_row_new = start_row + new_row + -- extend the end to fully include the range + local end_row_old = start_row + old_row + 1 + local end_row_new = start_row + new_row + 1 if new_row ~= old_row then if new_row < old_row then -- cgit From 6f75facb9d755e2e3a10a9a1d6d258a12578dc14 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Sun, 10 Dec 2023 22:18:48 +0900 Subject: fix(treesitter): improve vim.treesitter.foldexpr * Collect on_bytes and flush at the invocation of the scheduled callback to take account of commands that triggers multiple on_bytes. * More accurately track movement of folds so that foldexpr returns reasonable values even when the scheduled computation is not run yet. * Start computing folds from the line above (+ foldminlines) the changed lines to handle the folds that are removed due to the size limit. * Shrink folds that end at the line at which another fold starts to assign proper level to that line. * Use level '=' for lines that are not computed yet. --- runtime/lua/vim/treesitter/_fold.lua | 184 +++++++++++++++++++++-------------- 1 file changed, 110 insertions(+), 74 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua index d5626d0391..735627d29f 100644 --- a/runtime/lua/vim/treesitter/_fold.lua +++ b/runtime/lua/vim/treesitter/_fold.lua @@ -5,35 +5,20 @@ local Range = require('vim.treesitter._range') local api = vim.api ---@class TS.FoldInfo ----@field levels string[] the foldexpr value for each line +---@field levels string[] the foldexpr result for each line ---@field levels0 integer[] the raw fold levels ----@field private start_counts table ----@field private stop_counts table +---@field edits? {[1]: integer, [2]: integer} line range edited since the last invocation of the callback scheduled in on_bytes. 0-indexed, end-exclusive. local FoldInfo = {} FoldInfo.__index = FoldInfo ---@private function FoldInfo.new() return setmetatable({ - start_counts = {}, - stop_counts = {}, levels0 = {}, levels = {}, }, FoldInfo) end ----@package ----@param srow integer ----@param erow integer 0-indexed, exclusive -function FoldInfo:invalidate_range(srow, erow) - for i = srow + 1, erow do - self.start_counts[i] = nil - self.stop_counts[i] = nil - self.levels0[i] = nil - self.levels[i] = nil - end -end - --- Efficiently remove items from middle of a list a list. --- --- Calling table.remove() in a loop will re-index the tail of the table on @@ -59,8 +44,6 @@ end function FoldInfo:remove_range(srow, erow) list_remove(self.levels, srow + 1, erow) list_remove(self.levels0, srow + 1, erow) - list_remove(self.start_counts, srow + 1, erow) - list_remove(self.stop_counts, srow + 1, erow) end --- Efficiently insert items into the middle of a list. @@ -93,44 +76,35 @@ end ---@param srow integer ---@param erow integer 0-indexed, exclusive function FoldInfo:add_range(srow, erow) - list_insert(self.levels, srow + 1, erow, '-1') + list_insert(self.levels, srow + 1, erow, '=') list_insert(self.levels0, srow + 1, erow, -1) - list_insert(self.start_counts, srow + 1, erow, nil) - list_insert(self.stop_counts, srow + 1, erow, nil) -end - ----@package ----@param lnum integer -function FoldInfo:add_start(lnum) - self.start_counts[lnum] = (self.start_counts[lnum] or 0) + 1 end ---@package ----@param lnum integer -function FoldInfo:add_stop(lnum) - self.stop_counts[lnum] = (self.stop_counts[lnum] or 0) + 1 -end - ----@package ----@param lnum integer ----@return integer -function FoldInfo:get_start(lnum) - return self.start_counts[lnum] or 0 +---@param srow integer +---@param erow_old integer +---@param erow_new integer 0-indexed, exclusive +function FoldInfo:edit_range(srow, erow_old, erow_new) + if self.edits then + self.edits[1] = math.min(srow, self.edits[1]) + if erow_old <= self.edits[2] then + self.edits[2] = self.edits[2] + (erow_new - erow_old) + end + self.edits[2] = math.max(self.edits[2], erow_new) + else + self.edits = { srow, erow_new } + end end ---@package ----@param lnum integer ----@return integer -function FoldInfo:get_stop(lnum) - return self.stop_counts[lnum] or 0 -end - -local function trim_level(level) - local max_fold_level = vim.wo.foldnestmax - if level > max_fold_level then - return max_fold_level +---@return integer? srow +---@return integer? erow 0-indexed, exclusive +function FoldInfo:flush_edit() + if self.edits then + local srow, erow = self.edits[1], self.edits[2] + self.edits = nil + return srow, erow end - return level end --- If a parser doesn't have any ranges explicitly set, treesitter will @@ -158,22 +132,24 @@ local function get_folds_levels(bufnr, info, srow, erow, parse_injections) srow = srow or 0 erow = normalise_erow(bufnr, erow) - info:invalidate_range(srow, erow) - - local prev_start = -1 - local prev_stop = -1 - local parser = ts.get_parser(bufnr) parser:parse(parse_injections and { srow, erow } or nil) + local enter_counts = {} ---@type table + local leave_counts = {} ---@type table + local prev_start = -1 + local prev_stop = -1 + parser:for_each_tree(function(tree, ltree) local query = ts.query.get(ltree:lang(), 'folds') if not query then return end - for id, node, metadata in query:iter_captures(tree:root(), bufnr, srow, erow) do + -- Collect folds starting from srow - 1, because we should first subtract the folds that end at + -- srow - 1 from the level of srow - 1 to get accurate level of srow. + for id, node, metadata in query:iter_captures(tree:root(), bufnr, math.max(srow - 1, 0), erow) do if query.captures[id] == 'fold' then local range = ts.get_range(node, bufnr, metadata[id]) local start, _, stop, stop_col = Range.unpack4(range) @@ -190,8 +166,8 @@ local function get_folds_levels(bufnr, info, srow, erow, parse_injections) if fold_length > vim.wo.foldminlines and not (start == prev_start and stop == prev_stop) then - info:add_start(start + 1) - info:add_stop(stop + 1) + enter_counts[start + 1] = (enter_counts[start + 1] or 0) + 1 + leave_counts[stop + 1] = (leave_counts[stop + 1] or 0) + 1 prev_start = start prev_stop = stop end @@ -199,16 +175,15 @@ local function get_folds_levels(bufnr, info, srow, erow, parse_injections) end end) - local current_level = info.levels0[srow] or 0 + local nestmax = vim.wo.foldnestmax + local level0_prev = info.levels0[srow] or 0 + local leave_prev = leave_counts[srow] or 0 -- We now have the list of fold opening and closing, fill the gaps and mark where fold start for lnum = srow + 1, erow do - local last_trimmed_level = trim_level(current_level) - current_level = current_level + info:get_start(lnum) - info.levels0[lnum] = current_level - - local trimmed_level = trim_level(current_level) - current_level = current_level - info:get_stop(lnum) + local enter_line = enter_counts[lnum] or 0 + local leave_line = leave_counts[lnum] or 0 + local level0 = level0_prev - leave_prev + enter_line -- Determine if it's the start/end of a fold -- NB: vim's fold-expr interface does not have a mechanism to indicate that @@ -216,14 +191,36 @@ local function get_folds_levels(bufnr, info, srow, erow, parse_injections) -- ( \n ( \n )) \n (( \n ) \n ) -- versus -- ( \n ( \n ) \n ( \n ) \n ) - -- If it did have such a mechanism, (trimmed_level - last_trimmed_level) + -- Both are represented by ['>1', '>2', '2', '>2', '2', '1'], and + -- vim interprets as the second case. + -- If it did have such a mechanism, (clamped - clamped_prev) -- would be the correct number of starts to pass on. + local adjusted = level0 ---@type integer local prefix = '' - if trimmed_level - last_trimmed_level > 0 then + if enter_line > 0 then prefix = '>' + if leave_line > 0 then + -- If this line ends a fold f1 and starts a fold f2, then move f1's end to the previous line + -- so that f2 gets the correct level on this line. This may reduce the size of f1 below + -- foldminlines, but we don't handle it for simplicity. + adjusted = level0 - leave_line + leave_line = 0 + end + end + + -- Clamp at foldnestmax. + local clamped = adjusted + if adjusted > nestmax then + prefix = '' + clamped = nestmax end - info.levels[lnum] = prefix .. tostring(trimmed_level) + -- Record the "real" level, so that it can be used as "base" of later get_folds_levels(). + info.levels0[lnum] = adjusted + info.levels[lnum] = prefix .. tostring(clamped) + + leave_prev = leave_line + level0_prev = adjusted end end @@ -297,7 +294,8 @@ local function on_changedtree(bufnr, foldinfo, tree_changes) if ecol > 0 then erow = erow + 1 end - get_folds_levels(bufnr, foldinfo, srow, erow) + -- Start from `srow - foldminlines`, because this edit may have shrunken the fold below limit. + get_folds_levels(bufnr, foldinfo, math.max(srow - vim.wo.foldminlines, 0), erow) end if #tree_changes > 0 then foldupdate(bufnr) @@ -309,20 +307,46 @@ end ---@param foldinfo TS.FoldInfo ---@param start_row integer ---@param old_row integer +---@param old_col integer ---@param new_row integer -local function on_bytes(bufnr, foldinfo, start_row, old_row, new_row) +---@param new_col integer +local function on_bytes(bufnr, foldinfo, start_row, start_col, old_row, old_col, new_row, new_col) -- extend the end to fully include the range local end_row_old = start_row + old_row + 1 local end_row_new = start_row + new_row + 1 if new_row ~= old_row then + -- foldexpr can be evaluated before the scheduled callback is invoked. So it may observe the + -- outdated levels, which may spuriously open the folds that didn't change. So we should shift + -- folds as accurately as possible. For this to be perfectly accurate, we should track the + -- actual TSNodes that account for each fold, and compare the node's range with the edited + -- range. But for simplicity, we just check whether the start row is completely removed (e.g., + -- `dd`) or shifted (e.g., `o`). if new_row < old_row then - foldinfo:remove_range(end_row_new, end_row_old) + if start_col == 0 and new_row == 0 and new_col == 0 then + foldinfo:remove_range(start_row, start_row + (end_row_old - end_row_new)) + else + foldinfo:remove_range(end_row_new, end_row_old) + end else - foldinfo:add_range(start_row, end_row_new) + if start_col == 0 and old_row == 0 and old_col == 0 then + foldinfo:add_range(start_row, start_row + (end_row_new - end_row_old)) + else + foldinfo:add_range(end_row_old, end_row_new) + end end + foldinfo:edit_range(start_row, end_row_old, end_row_new) + + -- This callback must not use on_bytes arguments, because they can be outdated when the callback + -- is invoked. For example, `J` with non-zero count triggers multiple on_bytes before executing + -- the scheduled callback. So we should collect the edits. schedule_if_loaded(bufnr, function() - get_folds_levels(bufnr, foldinfo, start_row, end_row_new) + local srow, erow = foldinfo:flush_edit() + if not srow then + return + end + -- Start from `srow - foldminlines`, because this edit may have shrunken the fold below limit. + get_folds_levels(bufnr, foldinfo, math.max(srow - vim.wo.foldminlines, 0), erow) foldupdate(bufnr) end) end @@ -349,8 +373,8 @@ function M.foldexpr(lnum) on_changedtree(bufnr, foldinfos[bufnr], tree_changes) end, - on_bytes = function(_, _, start_row, _, _, old_row, _, _, new_row, _, _) - on_bytes(bufnr, foldinfos[bufnr], start_row, old_row, new_row) + on_bytes = function(_, _, start_row, start_col, _, old_row, old_col, _, new_row, new_col, _) + on_bytes(bufnr, foldinfos[bufnr], start_row, start_col, old_row, old_col, new_row, new_col) end, on_detach = function() @@ -362,6 +386,18 @@ function M.foldexpr(lnum) return foldinfos[bufnr].levels[lnum] or '0' end +api.nvim_create_autocmd('OptionSet', { + pattern = { 'foldminlines', 'foldnestmax' }, + desc = 'Refresh treesitter folds', + callback = function() + for _, bufnr in ipairs(vim.tbl_keys(foldinfos)) do + foldinfos[bufnr] = FoldInfo.new() + get_folds_levels(bufnr, foldinfos[bufnr]) + foldupdate(bufnr) + end + end, +}) + ---@package ---@return { [1]: string, [2]: string[] }[]|string function M.foldtext() -- cgit From 69ffbb76c237fcbba24de80f1b5346d92642e800 Mon Sep 17 00:00:00 2001 From: Will Hopkins Date: Tue, 12 Dec 2023 12:27:24 -0800 Subject: feat(iter): add `Iter.take` (#26525) --- runtime/lua/vim/iter.lua | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index e9c2b66bf2..8e602c406a 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -592,6 +592,41 @@ function ListIter.rfind(self, f) -- luacheck: no unused args self._head = self._tail end +--- Transforms an iterator to yield only the first n values. +--- +--- Example: +--- +--- ```lua +--- local it = vim.iter({ 1, 2, 3, 4 }):take(2) +--- it:next() +--- -- 1 +--- it:next() +--- -- 2 +--- it:next() +--- -- nil +--- ``` +--- +---@param n integer +---@return Iter +function Iter.take(self, n) + local next = self.next + local i = 0 + self.next = function() + if i < n then + i = i + 1 + return next(self) + end + end + return self +end + +---@private +function ListIter.take(self, n) + local inc = self._head < self._tail and 1 or -1 + self._tail = math.min(self._tail, self._head + n * inc) + return self +end + --- "Pops" a value from a |list-iterator| (gets the last value and decrements the tail). --- --- Example: -- cgit From e527842211188a5c069ef4f4759aa291353b707f Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Wed, 13 Dec 2023 08:14:30 -0600 Subject: fix(termcap): only call callback for requested capabilities (#26546) If multiple XTGETTCAP requests are active at once (for example, for requesting the Ms capability and truecolor capabilities), then the TermResponse autocommand may fire for capabilities that were not requested. Instead, make sure that the provided callback is only called for capabilities that were actually requested. --- runtime/lua/vim/termcap.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/termcap.lua b/runtime/lua/vim/termcap.lua index b88d9ac9ba..e48657b3c2 100644 --- a/runtime/lua/vim/termcap.lua +++ b/runtime/lua/vim/termcap.lua @@ -39,6 +39,12 @@ function M.query(caps, cb) local k, rest = resp:match('^\027P1%+r(%x+)(.*)$') if k and rest then local cap = vim.text.hexdecode(k) + if not pending[cap] then + -- Received a response for a capability we didn't request. This can happen if there are + -- multiple concurrent XTGETTCAP requests + return + end + local seq ---@type string? if rest:match('^=%x+$') then seq = vim.text -- cgit From 8122470f8310ae34bcd5e436e8474f9255eb16f2 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 13 Dec 2023 22:19:53 +0800 Subject: refactor(diagnostic): set sign by using extmark (#26193) after sign implementation refactor by using extmark, we can use `nvim_buf_set_extmark` to set diagnostic sign instead use `sign_define` --- runtime/lua/vim/diagnostic.lua | 61 +++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 34 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 99448982b4..729156584f 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -221,30 +221,6 @@ local underline_highlight_map = make_highlight_map('Underline') local floating_highlight_map = make_highlight_map('Floating') local sign_highlight_map = make_highlight_map('Sign') ----@private -local define_default_signs = (function() - local signs_defined = false - return function() - if signs_defined then - return - end - - for severity, sign_hl_name in pairs(sign_highlight_map) do - if vim.tbl_isempty(vim.fn.sign_getdefined(sign_hl_name)) then - local severity_name = M.severity[severity] - vim.fn.sign_define(sign_hl_name, { - text = (severity_name or 'U'):sub(1, 1), - texthl = sign_hl_name, - linehl = '', - numhl = '', - }) - end - end - - signs_defined = true - end -end)() - local function get_bufnr(bufnr) if not bufnr or bufnr == 0 then return api.nvim_get_current_buf() @@ -618,6 +594,14 @@ end --- * priority: (number, default 10) Base priority to use for signs. When --- {severity_sort} is used, the priority of a sign is adjusted based on --- its severity. Otherwise, all signs use the same priority. +--- * text: (table) A table mapping |diagnostic-severity| to the sign text +--- to display in the sign column. The default is to use "E", "W", "I", and "H" +--- for errors, warnings, information, and hints, respectively. Example: +---
lua
+---                     vim.diagnostic.config({
+---                       sign = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } }
+---                     })
+---                   
--- - float: Options for floating windows. See |vim.diagnostic.open_float()|. --- - update_in_insert: (default false) Update diagnostics in Insert mode (if false, --- diagnostics are updated on InsertLeave) @@ -868,8 +852,6 @@ M.handlers.signs = { diagnostics = filter_by_severity(opts.signs.severity, diagnostics) end - define_default_signs() - -- 10 is the default sign priority when none is explicitly specified local priority = opts.signs and opts.signs.priority or 10 local get_priority @@ -890,22 +872,33 @@ M.handlers.signs = { end local ns = M.get_namespace(namespace) - if not ns.user_data.sign_group then - ns.user_data.sign_group = string.format('vim.diagnostic.%s', ns.name) + if not ns.user_data.sign_ns then + ns.user_data.sign_ns = api.nvim_create_namespace('') + end + + local text = {} + for k in pairs(M.severity) do + if opts.signs.text and opts.signs.text[k] then + text[k] = opts.signs.text[k] + elseif type(k) == 'string' and not text[k] then + text[k] = string.sub(k, 1, 1):upper() + end end - local sign_group = ns.user_data.sign_group for _, diagnostic in ipairs(diagnostics) do - vim.fn.sign_place(0, sign_group, sign_highlight_map[diagnostic.severity], bufnr, { - priority = get_priority(diagnostic.severity), - lnum = diagnostic.lnum + 1, - }) + if api.nvim_buf_is_loaded(diagnostic.bufnr) then + api.nvim_buf_set_extmark(bufnr, ns.user_data.sign_ns, diagnostic.lnum, 0, { + sign_text = text[diagnostic.severity] or text[M.severity[diagnostic.severity]] or 'U', + sign_hl_group = sign_highlight_map[diagnostic.severity], + priority = get_priority(diagnostic.severity), + }) + end end end, hide = function(namespace, bufnr) local ns = M.get_namespace(namespace) if ns.user_data.sign_group and api.nvim_buf_is_valid(bufnr) then - vim.fn.sign_unplace(ns.user_data.sign_group, { buffer = bufnr }) + api.nvim_buf_clear_namespace(bufnr, ns.user_data.sign_ns, 0, -1) end end, } -- cgit From 29d5ff6ac4eade7996d14eec60a31ec6328a165d Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Wed, 13 Dec 2023 09:26:39 -0600 Subject: fix(diagnostic): check for sign namespace instead of sign group --- runtime/lua/vim/diagnostic.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 729156584f..d6db530bb0 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -897,7 +897,7 @@ M.handlers.signs = { end, hide = function(namespace, bufnr) local ns = M.get_namespace(namespace) - if ns.user_data.sign_group and api.nvim_buf_is_valid(bufnr) then + if ns.user_data.sign_ns and api.nvim_buf_is_valid(bufnr) then api.nvim_buf_clear_namespace(bufnr, ns.user_data.sign_ns, 0, -1) end end, -- cgit From 39112c72dd3722cd4a0770fc23c9d7269a9c2283 Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Wed, 13 Dec 2023 09:43:27 -0600 Subject: docs(diagnostic): fix typo in example --- runtime/lua/vim/diagnostic.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index d6db530bb0..1d76d1d7a0 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -598,9 +598,9 @@ end --- to display in the sign column. The default is to use "E", "W", "I", and "H" --- for errors, warnings, information, and hints, respectively. Example: ---
lua
----                     vim.diagnostic.config({
----                       sign = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } }
----                     })
+---                       vim.diagnostic.config({
+---                         signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } }
+---                       })
 ---                   
--- - float: Options for floating windows. See |vim.diagnostic.open_float()|. --- - update_in_insert: (default false) Update diagnostics in Insert mode (if false, -- cgit From a3b39784744f330b922117655811542202fcd85b Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Wed, 13 Dec 2023 09:54:04 -0600 Subject: feat(diagnostics): support numhl and linehl for diagnostic signs --- runtime/lua/vim/diagnostic.lua | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 1d76d1d7a0..0eb1ac7f15 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -602,6 +602,10 @@ end --- signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } } --- }) --- +--- * numhl: (table) A table mapping |diagnostic-severity| to the highlight +--- group used for the line number where the sign is placed. +--- * linehl: (table) A table mapping |diagnostic-severity| to the highlight group +--- used for the whole line the sign is placed in. --- - float: Options for floating windows. See |vim.diagnostic.open_float()|. --- - update_in_insert: (default false) Update diagnostics in Insert mode (if false, --- diagnostics are updated on InsertLeave) @@ -885,11 +889,16 @@ M.handlers.signs = { end end + local numhl = opts.signs.numhl or {} + local linehl = opts.signs.linehl or {} + for _, diagnostic in ipairs(diagnostics) do if api.nvim_buf_is_loaded(diagnostic.bufnr) then api.nvim_buf_set_extmark(bufnr, ns.user_data.sign_ns, diagnostic.lnum, 0, { sign_text = text[diagnostic.severity] or text[M.severity[diagnostic.severity]] or 'U', sign_hl_group = sign_highlight_map[diagnostic.severity], + number_hl_group = numhl[diagnostic.severity], + line_hl_group = linehl[diagnostic.severity], priority = get_priority(diagnostic.severity), }) end -- cgit From 5aa1ba3efe0597a5f508b8220961c75c3359ccdb Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Thu, 14 Dec 2023 07:16:21 +0900 Subject: fix(defaults): background detection in tmux (#26557) Wrap the query with passthrough sequence --- runtime/lua/vim/_defaults.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index b73681be04..2db82a04a1 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -298,7 +298,11 @@ if tty then end, }) - io.stdout:write('\027]11;?\007') + local query = '\027]11;?\007' + if os.getenv('TMUX') then + query = string.format('\027Ptmux;%s\027\\', query:gsub('\027', '\027\027')) + end + io.stdout:write(query) timer:start(1000, 0, function() -- Delete the autocommand if no response was received -- cgit From 619407eb548c7df56bc99b945338e9446f846fbb Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 14 Dec 2023 16:08:00 +0800 Subject: feat(nvim_open_term): convert LF => CRLF (#26384) Problem: Unlike termopen(), nvim_open_term() PTYs do not carriage-return the cursor on newline ("\n") input. nvim --clean :let chan_id = nvim_open_term(1, {}) :call chansend(chan_id, ["here", "are", "some", "lines"]) Actual behavior: here are some lines Expected behaviour: here are some lines Solution: Add `force_crlf` option, and enable it by default. --- runtime/lua/vim/_meta/api.lua | 2 ++ runtime/lua/vim/_meta/api_keysets.lua | 1 + 2 files changed, 3 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 4ad0a2e791..231e1c3404 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1446,6 +1446,8 @@ function vim.api.nvim_notify(msg, log_level, opts) end --- is sent as a "\r", not as a "\n". `textlock` applies. It --- is possible to call `nvim_chan_send()` directly in the --- callback however. ["input", term, bufnr, data] +--- • force_crlf: (boolean, default true) Convert "\n" to +--- "\r\n". --- @return integer function vim.api.nvim_open_term(buffer, opts) end diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index 6a3e574455..f64cdb8afd 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -217,6 +217,7 @@ error('Cannot require a meta file') --- @class vim.api.keyset.open_term --- @field on_input? function +--- @field force_crlf? boolean --- @class vim.api.keyset.option --- @field scope? string -- cgit From 97bea3163a3fe50359e7f6ffda747e28974a818a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 13 Dec 2023 12:00:11 +0000 Subject: feat(lsp): more annotations --- runtime/lua/vim/_editor.lua | 2 +- runtime/lua/vim/_meta/vvars.lua | 23 ++++ runtime/lua/vim/lsp.lua | 114 +++++++++++-------- runtime/lua/vim/lsp/_meta.lua | 3 +- runtime/lua/vim/lsp/buf.lua | 6 +- runtime/lua/vim/lsp/codelens.lua | 14 ++- runtime/lua/vim/lsp/diagnostic.lua | 9 ++ runtime/lua/vim/lsp/handlers.lua | 92 ++++++++------- runtime/lua/vim/lsp/inlay_hint.lua | 28 +++-- runtime/lua/vim/lsp/log.lua | 4 +- runtime/lua/vim/lsp/protocol.lua | 2 +- runtime/lua/vim/lsp/rpc.lua | 192 ++++++++++++++++++-------------- runtime/lua/vim/lsp/semantic_tokens.lua | 58 ++++++---- runtime/lua/vim/lsp/sync.lua | 28 +++-- runtime/lua/vim/lsp/util.lua | 4 +- 15 files changed, 354 insertions(+), 225 deletions(-) create mode 100644 runtime/lua/vim/_meta/vvars.lua (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 6cccbe8313..0bb1becf58 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -478,7 +478,7 @@ do end vim.g = make_dict_accessor('g', false) - vim.v = make_dict_accessor('v', false) + vim.v = make_dict_accessor('v', false) --[[@as vim.v]] vim.b = make_dict_accessor('b') vim.w = make_dict_accessor('w') vim.t = make_dict_accessor('t') diff --git a/runtime/lua/vim/_meta/vvars.lua b/runtime/lua/vim/_meta/vvars.lua new file mode 100644 index 0000000000..059ef04203 --- /dev/null +++ b/runtime/lua/vim/_meta/vvars.lua @@ -0,0 +1,23 @@ +--- @meta _ + +-- TODO(lewis6991): generate this and `:help vim-variable` + +--- @class vim.v +--- The count given for the last Normal mode command. Can be used +--- to get the count before a mapping. Read-only. Example: +--- ```vim +--- :map _x :echo "the count is " .. v:count +--- ``` +--- Note: The is required to remove the line range that you +--- get when typing ':' after a count. +--- When there are two counts, as in "3d2w", they are multiplied, +--- just like what happens in the command, "d6w" for the example. +--- Also used for evaluating the 'formatexpr' option. +--- @field count integer +--- +--- Line number for the 'foldexpr' |fold-expr|, 'formatexpr', +--- 'indentexpr' and 'statuscolumn' expressions, tab page number +--- for 'guitablabel' and 'guitabtooltip'. Only valid while one of +--- these expressions is being evaluated. Read-only when in the |sandbox|. +--- @field lnum integer +vim.v = ... diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 261a3aa5de..31aacd668b 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -257,7 +257,7 @@ end --- Validates a client configuration as given to |vim.lsp.start_client()|. --- ---@param config (lsp.ClientConfig) ----@return (string|fun(dispatchers:table):table) Command +---@return (string|fun(dispatchers:vim.rpc.Dispatchers):RpcClientPublic?) Command ---@return string[] Arguments ---@return string Encoding. local function validate_client_config(config) @@ -290,7 +290,7 @@ local function validate_client_config(config) 'flags.debounce_text_changes must be a number with the debounce time in milliseconds' ) - local cmd, cmd_args --- @type (string|fun(dispatchers:table):table), string[] + local cmd, cmd_args --- @type (string|fun(dispatchers:vim.rpc.Dispatchers):RpcClientPublic), string[] local config_cmd = config.cmd if type(config_cmd) == 'function' then cmd = config_cmd @@ -397,13 +397,14 @@ do end, }) + ---@param client lsp.Client ---@return CTGroup local function get_group(client) local allow_inc_sync = if_nil(client.config.flags.allow_incremental_sync, true) local change_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'change') local sync_kind = change_capability or protocol.TextDocumentSyncKind.None if not allow_inc_sync and change_capability == protocol.TextDocumentSyncKind.Incremental then - sync_kind = protocol.TextDocumentSyncKind.Full + sync_kind = protocol.TextDocumentSyncKind.Full --[[@as integer]] end return { sync_kind = sync_kind, @@ -572,7 +573,7 @@ do return end - local changes + local changes --- @type lsp.TextDocumentContentChangeEvent[] if sync_kind == protocol.TextDocumentSyncKind.None then return elseif sync_kind == protocol.TextDocumentSyncKind.Incremental then @@ -650,6 +651,7 @@ do end ---@private + ---@param buf_state CTBufferState function changetracking._reset_timer(buf_state) local timer = buf_state.timer if timer then @@ -663,6 +665,8 @@ do --- Flushes any outstanding change notification. ---@private + ---@param client lsp.Client + ---@param bufnr? integer function changetracking.flush(client, bufnr) local group = get_group(client) local state = state_by_group[group] @@ -685,7 +689,7 @@ end --- Default handler for the 'textDocument/didOpen' LSP notification. --- ---@param bufnr integer Number of the buffer, or 0 for current ----@param client table Client object +---@param client lsp.Client Client object local function text_document_did_open_handler(bufnr, client) changetracking.init(client, bufnr) if not vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then @@ -890,7 +894,7 @@ end ---@return string function lsp.status() local percentage = nil - local messages = {} + local messages = {} --- @type string[] for _, client in ipairs(vim.lsp.get_clients()) do for progress in client.progress do local value = progress.value @@ -913,12 +917,15 @@ function lsp.status() end -- Determines whether the given option can be set by `set_defaults`. +---@param bufnr integer +---@param option string +---@return boolean local function is_empty_or_default(bufnr, option) if vim.bo[bufnr][option] == '' then return true end - local info = vim.api.nvim_get_option_info2(option, { buf = bufnr }) + local info = api.nvim_get_option_info2(option, { buf = bufnr }) local scriptinfo = vim.tbl_filter(function(e) return e.sid == info.last_set_sid end, vim.fn.getscriptinfo()) @@ -932,6 +939,7 @@ end ---@private ---@param client lsp.Client +---@param bufnr integer function lsp._set_defaults(client, bufnr) if client.supports_method(ms.textDocument_definition) and is_empty_or_default(bufnr, 'tagfunc') @@ -1131,7 +1139,7 @@ function lsp.start_client(config) --- Returns the default handler if the user hasn't set a custom one. --- ---@param method (string) LSP method name - ---@return lsp-handler|nil The handler for the given method, if defined, or the default from |vim.lsp.handlers| + ---@return lsp.Handler|nil handler for the given method, if defined, or the default from |vim.lsp.handlers| local function resolve_handler(method) return handlers[method] or default_handlers[method] end @@ -1189,7 +1197,7 @@ function lsp.start_client(config) --- Invoked when the client operation throws an error. --- ---@param code (integer) Error code - ---@param err (...) Other arguments may be passed depending on the error kind + ---@param err any Other arguments may be passed depending on the error kind ---@see vim.lsp.rpc.client_errors for possible errors. Use ---`vim.lsp.rpc.client_errors[code]` to get a human-friendly name. function dispatch.on_error(code, err) @@ -1197,7 +1205,9 @@ function lsp.start_client(config) if config.on_error then local status, usererr = pcall(config.on_error, code, err) if not status then - local _ = log.error() and log.error(log_prefix, 'user on_error failed', { err = usererr }) + if log.error() then + log.error(log_prefix, 'user on_error failed', { err = usererr }) + end err_message(log_prefix, ' user on_error failed: ', tostring(usererr)) end end @@ -1283,7 +1293,7 @@ function lsp.start_client(config) end -- Start the RPC client. - local rpc + local rpc --- @type RpcClientPublic? if type(cmd) == 'function' then rpc = cmd(dispatch) else @@ -1306,9 +1316,10 @@ function lsp.start_client(config) rpc = rpc, offset_encoding = offset_encoding, config = config, - attached_buffers = {}, + attached_buffers = {}, --- @type table handlers = handlers, + --- @type table commands = config.commands or {}, --- @type table @@ -1346,7 +1357,7 @@ function lsp.start_client(config) verbose = 'verbose', } - local workspace_folders --- @type table[]? + local workspace_folders --- @type lsp.WorkspaceFolder[]? local root_uri --- @type string? local root_path --- @type string? if config.workspace_folders or config.root_dir then @@ -1426,7 +1437,9 @@ function lsp.start_client(config) end end - local _ = log.trace() and log.trace(log_prefix, 'initialize_params', initialize_params) + if log.trace() then + log.trace(log_prefix, 'initialize_params', initialize_params) + end rpc.request('initialize', initialize_params, function(init_err, result) assert(not init_err, tostring(init_err)) assert(result, 'server sent empty result') @@ -1439,7 +1452,7 @@ function lsp.start_client(config) -- when to send certain events to clients. client.server_capabilities = assert(result.capabilities, "initialize result doesn't contain capabilities") - client.server_capabilities = protocol.resolve_capabilities(client.server_capabilities) + client.server_capabilities = assert(protocol.resolve_capabilities(client.server_capabilities)) if client.server_capabilities.positionEncoding then client.offset_encoding = client.server_capabilities.positionEncoding @@ -1455,12 +1468,13 @@ function lsp.start_client(config) write_error(lsp.client_errors.ON_INIT_CALLBACK_ERROR, err) end end - local _ = log.info() - and log.info( + if log.info() then + log.info( log_prefix, 'server_capabilities', { server_capabilities = client.server_capabilities } ) + end -- Only assign after initialized. active_clients[client_id] = client @@ -1483,7 +1497,7 @@ function lsp.start_client(config) --- ---@param method string LSP method name. ---@param params table|nil LSP request params. - ---@param handler lsp-handler|nil Response |lsp-handler| for this method. + ---@param handler lsp.Handler|nil Response |lsp-handler| for this method. ---@param bufnr integer Buffer handle (0 for current). ---@return boolean status, integer|nil request_id {status} is a bool indicating ---whether the request was successful. If it is `false`, then it will @@ -1677,9 +1691,9 @@ function lsp.start_client(config) --- ---@param command lsp.Command ---@param context? {bufnr: integer} - ---@param handler? lsp-handler only called if a server command + ---@param handler? lsp.Handler only called if a server command function client._exec_cmd(command, context, handler) - context = vim.deepcopy(context or {}) + context = vim.deepcopy(context or {}) --[[@as lsp.HandlerContext]] context.bufnr = context.bufnr or api.nvim_get_current_buf() context.client_id = client.id local cmdname = command.command @@ -1749,29 +1763,32 @@ function lsp.start_client(config) return client_id end ----@private ----@fn text_document_did_change_handler(_, bufnr, changedtick, firstline, lastline, new_lastline, old_byte_size, old_utf32_size, old_utf16_size) --- Notify all attached clients that a buffer has changed. -local text_document_did_change_handler -do - text_document_did_change_handler = function( - _, - bufnr, - changedtick, - firstline, - lastline, - new_lastline - ) - -- Detach (nvim_buf_attach) via returning True to on_lines if no clients are attached - if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then - return true - end - util.buf_versions[bufnr] = changedtick - changetracking.send_changes(bufnr, firstline, lastline, new_lastline) +---@param _ integer +---@param bufnr integer +---@param changedtick integer +---@param firstline integer +---@param lastline integer +---@param new_lastline integer +---@return true? +local function text_document_did_change_handler( + _, + bufnr, + changedtick, + firstline, + lastline, + new_lastline +) + -- Detach (nvim_buf_attach) via returning True to on_lines if no clients are attached + if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then + return true end + util.buf_versions[bufnr] = changedtick + changetracking.send_changes(bufnr, firstline, lastline, new_lastline) end ---Buffer lifecycle handler for textDocument/didSave +--- @param bufnr integer local function text_document_did_save_handler(bufnr) bufnr = resolve_bufnr(bufnr) local uri = vim.uri_from_bufnr(bufnr) @@ -1797,7 +1814,7 @@ local function text_document_did_save_handler(bufnr) end local save_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'save') if save_capability then - local included_text + local included_text --- @type string? if type(save_capability) == 'table' and save_capability.includeText then included_text = text(bufnr) end @@ -1826,8 +1843,9 @@ function lsp.buf_attach_client(bufnr, client_id) }) bufnr = resolve_bufnr(bufnr) if not api.nvim_buf_is_loaded(bufnr) then - local _ = log.warn() - and log.warn(string.format('buf_attach_client called on unloaded buffer (id: %d): ', bufnr)) + if log.warn() then + log.warn(string.format('buf_attach_client called on unloaded buffer (id: %d): ', bufnr)) + end return false end local buffer_client_ids = all_buffer_active_clients[bufnr] @@ -2087,7 +2105,7 @@ api.nvim_create_autocmd('VimLeavePre', { client.stop() end - local timeouts = {} + local timeouts = {} --- @type table local max_timeout = 0 local send_kill = false @@ -2134,7 +2152,7 @@ api.nvim_create_autocmd('VimLeavePre', { ---@param bufnr (integer) Buffer handle, or 0 for current. ---@param method (string) LSP method name ---@param params table|nil Parameters to send to the server ----@param handler? lsp-handler See |lsp-handler| +---@param handler? lsp.Handler See |lsp-handler| --- If nil, follows resolution strategy defined in |lsp-handler-configuration| --- ---@return table client_request_ids Map of client-id:request-id pairs @@ -2152,7 +2170,7 @@ function lsp.buf_request(bufnr, method, params, handler) bufnr = resolve_bufnr(bufnr) local method_supported = false local clients = lsp.get_clients({ bufnr = bufnr }) - local client_request_ids = {} + local client_request_ids = {} --- @type table for _, client in ipairs(clients) do if client.supports_method(method, { bufnr = bufnr }) then method_supported = true @@ -2194,7 +2212,7 @@ end --- a `client_id:result` map. ---@return function cancel Function that cancels all requests. function lsp.buf_request_all(bufnr, method, params, handler) - local results = {} + local results = {} --- @type table local result_count = 0 local expected_result_count = 0 @@ -2324,6 +2342,7 @@ function lsp.formatexpr(opts) local params = util.make_formatting_params() local end_line = vim.fn.getline(end_lnum) --[[@as string]] local end_col = util._str_utfindex_enc(end_line, nil, client.offset_encoding) + --- @cast params +lsp.DocumentRangeFormattingParams params.range = { start = { line = start_lnum - 1, @@ -2378,7 +2397,7 @@ end ---@return table result is table of (client_id, client) pairs ---@deprecated Use |vim.lsp.get_clients()| instead. function lsp.buf_get_clients(bufnr) - local result = {} + local result = {} --- @type table for _, client in ipairs(lsp.get_clients({ bufnr = resolve_bufnr(bufnr) })) do result[client.id] = client end @@ -2432,7 +2451,7 @@ function lsp.for_each_buffer_client(bufnr, fn) end --- Function to manage overriding defaults for LSP handlers. ----@param handler (function) See |lsp-handler| +---@param handler (lsp.Handler) See |lsp-handler| ---@param override_config (table) Table containing the keys to override behavior of the {handler} function lsp.with(handler, override_config) return function(err, result, ctx, config) @@ -2497,6 +2516,7 @@ end --- arguments?: any[] --- --- The second argument is the `ctx` of |lsp-handler| +--- @type table lsp.commands = setmetatable({}, { __newindex = function(tbl, key, value) assert(type(key) == 'string', 'The key for commands in `vim.lsp.commands` must be a string') diff --git a/runtime/lua/vim/lsp/_meta.lua b/runtime/lua/vim/lsp/_meta.lua index acf799264e..559939c236 100644 --- a/runtime/lua/vim/lsp/_meta.lua +++ b/runtime/lua/vim/lsp/_meta.lua @@ -1,13 +1,14 @@ ---@meta error('Cannot require a meta file') ----@alias lsp-handler fun(err: lsp.ResponseError|nil, result: any, context: lsp.HandlerContext, config: table|nil): any? +---@alias lsp.Handler fun(err: lsp.ResponseError?, result: any, context: lsp.HandlerContext, config?: table): ...any ---@class lsp.HandlerContext ---@field method string ---@field client_id integer ---@field bufnr? integer ---@field params? any +---@field version? integer ---@class lsp.ResponseError ---@field code integer diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index cf9acc0808..2f754444e9 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -49,7 +49,7 @@ local function request_with_options(name, params, options) local req_handler if options then req_handler = function(err, result, ctx, config) - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) local handler = client.handlers[name] or vim.lsp.handlers[name] handler(err, result, ctx, vim.tbl_extend('force', config or {}, options)) end @@ -299,12 +299,12 @@ function M.rename(new_name, options) )[1] end - local try_use_client - try_use_client = function(idx, client) + local function try_use_client(idx, client) if not client then return end + --- @param name string local function rename(name) local params = util.make_position_params(win, client.offset_encoding) params.newName = name diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index 9cccaa1d66..199da288f4 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -6,7 +6,7 @@ local M = {} --- bufnr → true|nil --- to throttle refreshes to at most one at a time -local active_refreshes = {} +local active_refreshes = {} --- @type table ---@type table> --- bufnr -> client_id -> lenses @@ -75,7 +75,7 @@ end function M.run() local line = api.nvim_win_get_cursor(0)[1] local bufnr = api.nvim_get_current_buf() - local options = {} + local options = {} --- @type {client: integer, lens: lsp.CodeLens}[] local lenses_by_client = lens_cache_by_buf[bufnr] or {} for client, lenses in pairs(lenses_by_client) do for _, lens in pairs(lenses) do @@ -230,6 +230,7 @@ local function resolve_lenses(lenses, bufnr, client_id, callback) if lens.command then countdown() else + assert(client) client.request('codeLens/resolve', lens, function(_, result) if api.nvim_buf_is_loaded(bufnr) and result and result.command then lens.command = result.command @@ -257,10 +258,13 @@ end --- |lsp-handler| for the method `textDocument/codeLens` --- +---@param ctx lsp.HandlerContext function M.on_codelens(err, result, ctx, _) if err then - active_refreshes[ctx.bufnr] = nil - local _ = log.error() and log.error('codelens', err) + active_refreshes[assert(ctx.bufnr)] = nil + if log.error() then + log.error('codelens', err) + end return end @@ -270,7 +274,7 @@ function M.on_codelens(err, result, ctx, _) -- once resolved. M.display(result, ctx.bufnr, ctx.client_id) resolve_lenses(result, ctx.bufnr, ctx.client_id, function() - active_refreshes[ctx.bufnr] = nil + active_refreshes[assert(ctx.bufnr)] = nil M.display(result, ctx.bufnr, ctx.client_id) end) end diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index b6f0cfa0b3..cba5b66672 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -37,6 +37,10 @@ local function severity_vim_to_lsp(severity) return severity end +---@param lines string[] +---@param lnum integer +---@param col integer +---@param offset_encoding string ---@return integer local function line_byte_from_position(lines, lnum, col, offset_encoding) if not lines or offset_encoding == 'utf-8' then @@ -52,6 +56,8 @@ local function line_byte_from_position(lines, lnum, col, offset_encoding) return col end +---@param bufnr integer +---@return string[] local function get_buf_lines(bufnr) if vim.api.nvim_buf_is_loaded(bufnr) then return vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) @@ -223,6 +229,7 @@ end --- ) --- ``` --- +---@param ctx lsp.HandlerContext ---@param config table Configuration table (see |vim.diagnostic.config()|). function M.on_publish_diagnostics(_, result, ctx, config) local client_id = ctx.client_id @@ -284,6 +291,7 @@ end --- ) --- ``` --- +---@param ctx lsp.HandlerContext ---@param config table Configuration table (see |vim.diagnostic.config()|). function M.on_diagnostic(_, result, ctx, config) local client_id = ctx.client_id @@ -400,6 +408,7 @@ end local bufstates = {} --- Disable pull diagnostics for a buffer +--- @param bufnr integer --- @private local function disable(bufnr) local bufstate = bufstates[bufnr] diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 6fde55cf04..c03a17fa59 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -4,6 +4,7 @@ local ms = protocol.Methods local util = require('vim.lsp.util') local api = vim.api +--- @type table local M = {} -- FIXME: DOC: Expose in vimdocs @@ -108,8 +109,7 @@ end --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability M[ms.client_registerCapability] = function(_, result, ctx) local client_id = ctx.client_id - ---@type lsp.Client - local client = vim.lsp.get_client_by_id(client_id) + local client = assert(vim.lsp.get_client_by_id(client_id)) client.dynamic_capabilities:register(result.registrations) for bufnr, _ in pairs(client.attached_buffers) do @@ -139,7 +139,7 @@ end --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_unregisterCapability M[ms.client_unregisterCapability] = function(_, result, ctx) local client_id = ctx.client_id - local client = vim.lsp.get_client_by_id(client_id) + local client = assert(vim.lsp.get_client_by_id(client_id)) client.dynamic_capabilities:unregister(result.unregisterations) for _, unreg in ipairs(result.unregisterations) do @@ -158,7 +158,7 @@ M[ms.workspace_applyEdit] = function(_, workspace_edit, ctx) ) -- TODO(ashkan) Do something more with label? local client_id = ctx.client_id - local client = vim.lsp.get_client_by_id(client_id) + local client = assert(vim.lsp.get_client_by_id(client_id)) if workspace_edit.label then print('Workspace edit', workspace_edit.label) end @@ -231,22 +231,23 @@ end M[ms.textDocument_references] = function(_, result, ctx, config) if not result or vim.tbl_isempty(result) then vim.notify('No references found') - else - local client = vim.lsp.get_client_by_id(ctx.client_id) - config = config or {} - local title = 'References' - local items = util.locations_to_items(result, client.offset_encoding) + return + end - if config.loclist then - vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx }) - api.nvim_command('lopen') - elseif config.on_list then - assert(type(config.on_list) == 'function', 'on_list is not a function') - config.on_list({ title = title, items = items, context = ctx }) - else - vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx }) - api.nvim_command('botright copen') - end + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) + config = config or {} + local title = 'References' + local items = util.locations_to_items(result, client.offset_encoding) + + if config.loclist then + vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx }) + api.nvim_command('lopen') + elseif config.on_list then + assert(type(config.on_list) == 'function', 'on_list is not a function') + config.on_list({ title = title, items = items, context = ctx }) + else + vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx }) + api.nvim_command('botright copen') end end @@ -259,26 +260,27 @@ end --- ---@param map_result function `((resp, bufnr) -> list)` to convert the response ---@param entity string name of the resource used in a `not found` error message ----@param title_fn function Function to call to generate list title +---@param title_fn fun(ctx: lsp.HandlerContext): string Function to call to generate list title +---@return lsp.Handler local function response_to_list(map_result, entity, title_fn) return function(_, result, ctx, config) if not result or vim.tbl_isempty(result) then vim.notify('No ' .. entity .. ' found') + return + end + config = config or {} + local title = title_fn(ctx) + local items = map_result(result, ctx.bufnr) + + if config.loclist then + vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx }) + api.nvim_command('lopen') + elseif config.on_list then + assert(type(config.on_list) == 'function', 'on_list is not a function') + config.on_list({ title = title, items = items, context = ctx }) else - config = config or {} - local title = title_fn(ctx) - local items = map_result(result, ctx.bufnr) - - if config.loclist then - vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx }) - api.nvim_command('lopen') - elseif config.on_list then - assert(type(config.on_list) == 'function', 'on_list is not a function') - config.on_list({ title = title, items = items, context = ctx }) - else - vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx }) - api.nvim_command('botright copen') - end + vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx }) + api.nvim_command('botright copen') end end end @@ -304,7 +306,7 @@ M[ms.textDocument_rename] = function(_, result, ctx, _) vim.notify("Language server couldn't provide rename result", vim.log.levels.INFO) return end - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) util.apply_workspace_edit(result, client.offset_encoding) end @@ -313,7 +315,7 @@ M[ms.textDocument_rangeFormatting] = function(_, result, ctx, _) if not result then return end - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) util.apply_text_edits(result, ctx.bufnr, client.offset_encoding) end @@ -322,7 +324,7 @@ M[ms.textDocument_formatting] = function(_, result, ctx, _) if not result then return end - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) util.apply_text_edits(result, ctx.bufnr, client.offset_encoding) end @@ -331,7 +333,8 @@ M[ms.textDocument_completion] = function(_, result, _, _) if vim.tbl_isempty(result or {}) then return end - local row, col = unpack(api.nvim_win_get_cursor(0)) + local cursor = api.nvim_win_get_cursor(0) + local row, col = cursor[1], cursor[2] local line = assert(api.nvim_buf_get_lines(0, row - 1, row, false)[1]) local line_to_cursor = line:sub(col + 1) local textMatch = vim.fn.match(line_to_cursor, '\\k*$') @@ -354,6 +357,7 @@ end --- ) --- ``` --- +---@param ctx lsp.HandlerContext ---@param config table Configuration table. --- - border: (default=nil) --- - Add borders to the floating window @@ -394,14 +398,16 @@ M[ms.textDocument_hover] = M.hover --- Jumps to a location. Used as a handler for multiple LSP methods. ---@param _ nil not used ---@param result (table) result of LSP method; a location or a list of locations. ----@param ctx (table) table containing the context of the request, including the method +---@param ctx (lsp.HandlerContext) table containing the context of the request, including the method ---(`textDocument/definition` can return `Location` or `Location[]` local function location_handler(_, result, ctx, config) if result == nil or vim.tbl_isempty(result) then - local _ = log.info() and log.info(ctx.method, 'No location found') + if log.info() then + log.info(ctx.method, 'No location found') + end return nil end - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) config = config or {} @@ -450,7 +456,7 @@ M[ms.textDocument_implementation] = location_handler --- ``` --- ---@param result table Response from the language server ----@param ctx table Client context +---@param ctx lsp.HandlerContext Client context ---@param config table Configuration table. --- - border: (default=nil) --- - Add borders to the floating window @@ -470,7 +476,7 @@ function M.signature_help(_, result, ctx, config) end return end - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) local triggers = vim.tbl_get(client.server_capabilities, 'signatureHelpProvider', 'triggerCharacters') local ft = vim.bo[ctx.bufnr].filetype diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua index 4f7a3b0076..ce1680549e 100644 --- a/runtime/lua/vim/lsp/inlay_hint.lua +++ b/runtime/lua/vim/lsp/inlay_hint.lua @@ -17,13 +17,17 @@ local augroup = api.nvim_create_augroup('vim_lsp_inlayhint', {}) --- |lsp-handler| for the method `textDocument/inlayHint` --- Store hints for a specific buffer and client +---@param result lsp.InlayHint[]? +---@param ctx lsp.HandlerContext ---@private function M.on_inlayhint(err, result, ctx, _) if err then - local _ = log.error() and log.error('inlayhint', err) + if log.error() then + log.error('inlayhint', err) + end return end - local bufnr = ctx.bufnr + local bufnr = assert(ctx.bufnr) if util.buf_versions[bufnr] ~= ctx.version then return end @@ -40,7 +44,7 @@ function M.on_inlayhint(err, result, ctx, _) bufstate.version = ctx.version end local hints_by_client = bufstate.client_hint - local client = vim.lsp.get_client_by_id(client_id) + local client = assert(vim.lsp.get_client_by_id(client_id)) local new_hints_by_lnum = vim.defaulttable() local num_unprocessed = #result @@ -52,6 +56,8 @@ function M.on_inlayhint(err, result, ctx, _) end local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false) + ---@param position lsp.Position + ---@return integer local function pos_to_byte(position) local col = position.character if col > 0 then @@ -78,6 +84,7 @@ function M.on_inlayhint(err, result, ctx, _) end --- |lsp-handler| for the method `textDocument/inlayHint/refresh` +---@param ctx lsp.HandlerContext ---@private function M.on_refresh(err, _, ctx, _) if err then @@ -212,7 +219,7 @@ local function clear(bufnr) end local bufstate = bufstates[bufnr] local client_lens = (bufstate or {}).client_hint or {} - local client_ids = vim.tbl_keys(client_lens) + local client_ids = vim.tbl_keys(client_lens) --- @type integer[] for _, iter_client_id in ipairs(client_ids) do if bufstate then bufstate.client_hint[iter_client_id] = {} @@ -236,7 +243,7 @@ end --- Refresh inlay hints, only if we have attached clients that support it ---@param bufnr (integer) Buffer handle, or 0 for current ----@param opts? table Additional options to pass to util._refresh +---@param opts? lsp.util.RefreshOptions Additional options to pass to util._refresh ---@private local function _refresh(bufnr, opts) opts = opts or {} @@ -312,7 +319,7 @@ api.nvim_set_decoration_provider(namespace, { if bufstate.version ~= util.buf_versions[bufnr] then return end - local hints_by_client = bufstate.client_hint + local hints_by_client = assert(bufstate.client_hint) for lnum = topline, botline do if bufstate.applied[lnum] ~= bufstate.version then @@ -321,14 +328,15 @@ api.nvim_set_decoration_provider(namespace, { local line_hints = hints_by_lnum[lnum] or {} for _, hint in pairs(line_hints) do local text = '' - if type(hint.label) == 'string' then - text = hint.label + local label = hint.label + if type(label) == 'string' then + text = label else - for _, part in ipairs(hint.label) do + for _, part in ipairs(label) do text = text .. part.value end end - local vt = {} + local vt = {} --- @type {[1]: string, [2]: string?}[] if hint.paddingLeft then vt[#vt + 1] = { ' ' } end diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua index 6d2e0bc292..00433474fe 100644 --- a/runtime/lua/vim/lsp/log.lua +++ b/runtime/lua/vim/lsp/log.lua @@ -91,7 +91,9 @@ do -- -- Recommended usage: -- ``` - -- local _ = log.warn() and log.warn("123") + -- if log.warn() then + -- log.warn("123") + -- end -- ``` -- -- This way you can avoid string allocations if the log level isn't high enough. diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index a7c3914834..b2a92cd1ee 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -891,7 +891,7 @@ end --- Creates a normalized object describing LSP server capabilities. ---@param server_capabilities table Table of capabilities supported by the server ----@return table|nil Normalized table of capabilities +---@return lsp.ServerCapabilities|nil Normalized table of capabilities function protocol.resolve_capabilities(server_capabilities) local TextDocumentSyncKind = protocol.TextDocumentSyncKind local textDocumentSync = server_capabilities.textDocumentSync diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 6ab5708721..61ad1e479c 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -26,23 +26,42 @@ local function format_message_with_content_length(encoded_message) }) end +local function log_error(...) + if log.error() then + log.error(...) + end +end + +local function log_info(...) + if log.info() then + log.info(...) + end +end + +local function log_debug(...) + if log.debug() then + log.debug(...) + end +end + --- Parses an LSP Message's header --- ---@param header string: The header to parse. ---@return table # parsed headers local function parse_headers(header) assert(type(header) == 'string', 'header must be a string') - local headers = {} + local headers = {} --- @type table for line in vim.gsplit(header, '\r\n', { plain = true }) do if line == '' then break end + --- @type string?, string? local key, value = line:match('^%s*(%S+)%s*:%s*(.+)%s*$') if key then - key = key:lower():gsub('%-', '_') + key = key:lower():gsub('%-', '_') --- @type string headers[key] = value else - local _ = log.error() and log.error('invalid header line %q', line) + log_error('invalid header line %q', line) error(string.format('invalid header line %q', line)) end end @@ -96,17 +115,17 @@ local function request_parser_loop() end local body = table.concat(body_chunks) -- Yield our data. - buffer = rest - .. ( - coroutine.yield(headers, body) - or error('Expected more data for the body. The server may have died.') - ) -- TODO hmm. + + --- @type string + local data = coroutine.yield(headers, body) + or error('Expected more data for the body. The server may have died.') + buffer = rest .. data else -- Get more data since we don't have enough. - buffer = buffer - .. ( - coroutine.yield() or error('Expected more data for the header. The server may have died.') - ) -- TODO hmm. + --- @type string + local data = coroutine.yield() + or error('Expected more data for the header. The server may have died.') + buffer = buffer .. data end end end @@ -138,7 +157,7 @@ function M.format_rpc_error(err) -- There is ErrorCodes in the LSP specification, -- but in ResponseError.code it is not used and the actual type is number. - local code + local code --- @type string if protocol.ErrorCodes[err.code] then code = string.format('code_name = %s,', protocol.ErrorCodes[err.code]) else @@ -174,48 +193,51 @@ function M.rpc_response_error(code, message, data) }) end -local default_dispatchers = {} +--- @class vim.rpc.Dispatchers +--- @field notification fun(method: string, params: table) +--- @field server_request fun(method: string, params: table): any?, string? +--- @field on_exit fun(code: integer, signal: integer) +--- @field on_error fun(code: integer, err: any) ----@private ---- Default dispatcher for notifications sent to an LSP server. ---- ----@param method (string) The invoked LSP method ----@param params (table): Parameters for the invoked LSP method -function default_dispatchers.notification(method, params) - local _ = log.debug() and log.debug('notification', method, params) -end - ----@private ---- Default dispatcher for requests sent to an LSP server. ---- ----@param method (string) The invoked LSP method ----@param params (table): Parameters for the invoked LSP method ----@return nil ----@return table `vim.lsp.protocol.ErrorCodes.MethodNotFound` -function default_dispatchers.server_request(method, params) - local _ = log.debug() and log.debug('server_request', method, params) - return nil, M.rpc_response_error(protocol.ErrorCodes.MethodNotFound) -end - ----@private ---- Default dispatcher for when a client exits. ---- ----@param code (integer): Exit code ----@param signal (integer): Number describing the signal used to terminate (if ----any) -function default_dispatchers.on_exit(code, signal) - local _ = log.info() and log.info('client_exit', { code = code, signal = signal }) -end +--- @type vim.rpc.Dispatchers +local default_dispatchers = { + --- Default dispatcher for notifications sent to an LSP server. + --- + ---@param method (string) The invoked LSP method + ---@param params (table): Parameters for the invoked LSP method + notification = function(method, params) + log_debug('notification', method, params) + end, ----@private ---- Default dispatcher for client errors. ---- ----@param code (integer): Error code ----@param err (any): Details about the error ----any) -function default_dispatchers.on_error(code, err) - local _ = log.error() and log.error('client_error:', M.client_errors[code], err) -end + --- Default dispatcher for requests sent to an LSP server. + --- + ---@param method (string) The invoked LSP method + ---@param params (table): Parameters for the invoked LSP method + ---@return nil + ---@return table, `vim.lsp.protocol.ErrorCodes.MethodNotFound` + server_request = function(method, params) + log_debug('server_request', method, params) + return nil, M.rpc_response_error(protocol.ErrorCodes.MethodNotFound) + end, + + --- Default dispatcher for when a client exits. + --- + ---@param code (integer): Exit code + ---@param signal (integer): Number describing the signal used to terminate (if + ---any) + on_exit = function(code, signal) + log_info('client_exit', { code = code, signal = signal }) + end, + + --- Default dispatcher for client errors. + --- + ---@param code (integer): Error code + ---@param err (any): Details about the error + ---any) + on_error = function(code, err) + log_error('client_error:', M.client_errors[code], err) + end, +} ---@private function M.create_read_loop(handle_body, on_no_chunk, on_error) @@ -248,8 +270,8 @@ end ---@class RpcClient ---@field message_index integer ----@field message_callbacks table ----@field notify_reply_callbacks table +---@field message_callbacks table +---@field notify_reply_callbacks table ---@field transport table ---@field dispatchers table @@ -258,7 +280,7 @@ local Client = {} ---@private function Client:encode_and_send(payload) - local _ = log.debug() and log.debug('rpc.send', payload) + log_debug('rpc.send', payload) if self.transport.is_closing() then return false end @@ -267,7 +289,7 @@ function Client:encode_and_send(payload) return true end ----@private +---@package --- Sends a notification to the LSP server. ---@param method (string) The invoked LSP method ---@param params (any): Parameters for the invoked LSP method @@ -291,7 +313,7 @@ function Client:send_response(request_id, err, result) }) end ----@private +---@package --- Sends a request to the LSP server and runs {callback} upon response. --- ---@param method (string) The invoked LSP method @@ -329,7 +351,7 @@ function Client:request(method, params, callback, notify_reply_callback) end end ----@private +---@package function Client:on_error(errkind, ...) assert(M.client_errors[errkind]) -- TODO what to do if this fails? @@ -354,17 +376,17 @@ end -- time and log them. This would require storing the timestamp. I could call -- them with an error then, perhaps. ----@private +---@package function Client:handle_body(body) local ok, decoded = pcall(vim.json.decode, body, { luanil = { object = true } }) if not ok then self:on_error(M.client_errors.INVALID_SERVER_JSON, decoded) return end - local _ = log.debug() and log.debug('rpc.receive', decoded) + log_debug('rpc.receive', decoded) if type(decoded.method) == 'string' and decoded.id then - local err + local err --- @type table? -- Schedule here so that the users functions don't trigger an error and -- we can still use the result. schedule(function() @@ -376,11 +398,10 @@ function Client:handle_body(body) decoded.method, decoded.params ) - local _ = log.debug() - and log.debug( - 'server_request: callback result', - { status = status, result = result, err = err } - ) + log_debug( + 'server_request: callback result', + { status = status, result = result, err = err } + ) if status then if result == nil and err == nil then error( @@ -431,7 +452,7 @@ function Client:handle_body(body) if decoded.error then local mute_error = false if decoded.error.code == protocol.ErrorCodes.RequestCancelled then - local _ = log.debug() and log.debug('Received cancellation ack', decoded) + log_debug('Received cancellation ack', decoded) mute_error = true end @@ -467,7 +488,7 @@ function Client:handle_body(body) ) else self:on_error(M.client_errors.NO_RESULT_CALLBACK_FOUND, decoded) - local _ = log.error() and log.error('No callback found for server response id ' .. result_id) + log_error('No callback found for server response id ' .. result_id) end elseif type(decoded.method) == 'string' then -- Notification @@ -495,7 +516,14 @@ local function new_client(dispatchers, transport) return setmetatable(state, { __index = Client }) end +--- @class RpcClientPublic +--- @field is_closing fun(): boolean +--- @field terminate fun() +--- @field request fun(method: string, params: table?, callback: function, notify_reply_callbacks?: function) +--- @field notify fun(methid: string, params: table?): boolean + ---@param client RpcClient +---@return RpcClientPublic local function public_client(client) local result = {} @@ -531,12 +559,14 @@ local function public_client(client) return result end +--- @param dispatchers vim.rpc.Dispatchers? +--- @return vim.rpc.Dispatchers local function merge_dispatchers(dispatchers) if dispatchers then local user_dispatchers = dispatchers dispatchers = {} for dispatch_name, default_dispatch in pairs(default_dispatchers) do - local user_dispatcher = user_dispatchers[dispatch_name] + local user_dispatcher = user_dispatchers[dispatch_name] --- @type function if user_dispatcher then if type(user_dispatcher) ~= 'function' then error(string.format('dispatcher.%s must be a function', dispatch_name)) @@ -547,8 +577,10 @@ local function merge_dispatchers(dispatchers) then user_dispatcher = schedule_wrap(user_dispatcher) end + --- @diagnostic disable-next-line:no-unknown dispatchers[dispatch_name] = user_dispatcher else + --- @diagnostic disable-next-line:no-unknown dispatchers[dispatch_name] = default_dispatch end end @@ -567,7 +599,7 @@ end function M.connect(host, port) return function(dispatchers) dispatchers = merge_dispatchers(dispatchers) - local tcp = uv.new_tcp() + local tcp = assert(uv.new_tcp()) local closing = false local transport = { write = function(msg) @@ -624,15 +656,13 @@ end --- server process. May contain: --- - {cwd} (string) Working directory for the LSP server process --- - {env} (table) Additional environment variables for LSP server process ----@return table|nil Client RPC object, with these methods: +---@return RpcClientPublic|nil Client RPC object, with these methods: --- - `notify()` |vim.lsp.rpc.notify()| --- - `request()` |vim.lsp.rpc.request()| --- - `is_closing()` returns a boolean indicating if the RPC is closing. --- - `terminate()` terminates the RPC client. function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) - if log.info() then - log.info('Starting RPC client', { cmd = cmd, args = cmd_args, extra = extra_spawn_params }) - end + log_info('Starting RPC client', { cmd = cmd, args = cmd_args, extra = extra_spawn_params }) validate({ cmd = { cmd, 's' }, @@ -671,8 +701,8 @@ function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) end) local stderr_handler = function(_, chunk) - if chunk and log.error() then - log.error('rpc', cmd, 'stderr', chunk) + if chunk then + log_error('rpc', cmd, 'stderr', chunk) end end @@ -697,13 +727,13 @@ function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) if not ok then local err = sysobj_or_err --[[@as string]] - local msg = string.format('Spawning language server with cmd: `%s` failed', cmd) + local sfx --- @type string if string.match(err, 'ENOENT') then - msg = msg - .. '. The language server is either not installed, missing from PATH, or not executable.' + sfx = '. The language server is either not installed, missing from PATH, or not executable.' else - msg = msg .. string.format(' with error message: %s', err) + sfx = string.format(' with error message: %s', err) end + local msg = string.format('Spawning language server with cmd: `%s` failed%s', cmd, sfx) vim.notify(msg, vim.log.levels.WARN) return end diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index a5831c0beb..b0cec0dd0e 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -10,7 +10,7 @@ local uv = vim.uv --- @field start_col integer start column 0-based --- @field end_col integer end column 0-based --- @field type string token type as string ---- @field modifiers table token modifiers as a set. E.g., { static = true, readonly = true } +--- @field modifiers table token modifiers as a set. E.g., { static = true, readonly = true } --- @field marked boolean whether this token has had extmarks applied --- --- @class STCurrentResult @@ -21,8 +21,8 @@ local uv = vim.uv --- @field namespace_cleared? boolean whether the namespace was cleared for this result yet --- --- @class STActiveRequest ---- @field request_id integer the LSP request ID of the most recent request sent to the server ---- @field version integer the document version associated with the most recent request +--- @field request_id? integer the LSP request ID of the most recent request sent to the server +--- @field version? integer the document version associated with the most recent request --- --- @class STClientState --- @field namespace integer @@ -72,9 +72,11 @@ end --- Extracts modifier strings from the encoded number in the token array --- +---@param x integer +---@param modifiers_table table ---@return table local function modifiers_from_number(x, modifiers_table) - local modifiers = {} + local modifiers = {} ---@type table local idx = 1 while x > 0 do if bit.band(x, 1) == 1 then @@ -89,20 +91,24 @@ end --- Converts a raw token list to a list of highlight ranges used by the on_win callback --- +---@param data integer[] +---@param bufnr integer +---@param client lsp.Client +---@param request STActiveRequest ---@return STTokenRange[] local function tokens_to_ranges(data, bufnr, client, request) local legend = client.server_capabilities.semanticTokensProvider.legend local token_types = legend.tokenTypes local token_modifiers = legend.tokenModifiers local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false) - local ranges = {} + local ranges = {} ---@type STTokenRange[] local start = uv.hrtime() local ms_to_ns = 1000 * 1000 local yield_interval_ns = 5 * ms_to_ns local co, is_main = coroutine.running() - local line + local line ---@type integer? local start_char = 0 for i = 1, #data, 5 do -- if this function is called from the main coroutine, let it run to completion with no yield @@ -167,6 +173,7 @@ end --- ---@private ---@param bufnr integer +---@return STHighlighter function STHighlighter.new(bufnr) local self = setmetatable({}, { __index = STHighlighter }) @@ -221,7 +228,7 @@ function STHighlighter.new(bufnr) return self end ----@private +---@package function STHighlighter:destroy() for client_id, _ in pairs(self.client_state) do self:detach(client_id) @@ -231,7 +238,7 @@ function STHighlighter:destroy() STHighlighter.active[self.bufnr] = nil end ----@private +---@package function STHighlighter:attach(client_id) local state = self.client_state[client_id] if not state then @@ -244,7 +251,7 @@ function STHighlighter:attach(client_id) end end ----@private +---@package function STHighlighter:detach(client_id) local state = self.client_state[client_id] if state then @@ -267,7 +274,7 @@ end --- Finally, if the request was successful, the requestId and document version --- are saved to facilitate document synchronization in the response. --- ----@private +---@package function STHighlighter:send_request() local version = util.buf_versions[self.bufnr] @@ -303,7 +310,8 @@ function STHighlighter:send_request() -- look client up again using ctx.client_id instead of using a captured -- client object local c = vim.lsp.get_client_by_id(ctx.client_id) - local highlighter = STHighlighter.active[ctx.bufnr] + local bufnr = assert(ctx.bufnr) + local highlighter = STHighlighter.active[bufnr] if not err and c and highlighter then coroutine.wrap(STHighlighter.process_response)(highlighter, response, c, version) end @@ -328,6 +336,7 @@ end --- Finally, a redraw command is issued to force nvim to redraw the screen to --- pick up changed highlight tokens. --- +---@param response lsp.SemanticTokens|lsp.SemanticTokensDelta ---@private function STHighlighter:process_response(response, client, version) local state = self.client_state[client.id] @@ -348,15 +357,15 @@ function STHighlighter:process_response(response, client, version) -- if we have a response to a delta request, update the state of our tokens -- appropriately. if it's a full response, just use that - local tokens + local tokens ---@type integer[] local token_edits = response.edits if token_edits then table.sort(token_edits, function(a, b) return a.start < b.start end) - tokens = {} - local old_tokens = state.current_result.tokens + tokens = {} --- @type integer[] + local old_tokens = assert(state.current_result.tokens) local idx = 1 for _, token_edit in ipairs(token_edits) do vim.list_extend(tokens, old_tokens, idx, token_edit.start) @@ -404,7 +413,9 @@ end --- handler to avoid the "blink" that occurs due to the timing between the --- response handler and the actual redraw. --- ----@private +---@package +---@param topline integer +---@param botline integer function STHighlighter:on_win(topline, botline) for client_id, state in pairs(self.client_state) do local current_result = state.current_result @@ -450,7 +461,7 @@ function STHighlighter:on_win(topline, botline) end local ft = vim.bo[self.bufnr].filetype - local highlights = current_result.highlights + local highlights = assert(current_result.highlights) local first = lower_bound(highlights, topline, 1, #highlights + 1) local last = upper_bound(highlights, botline, first, #highlights + 1) - 1 @@ -480,7 +491,7 @@ end --- Reset the buffer's highlighting state and clears the extmark highlights. --- ----@private +---@package function STHighlighter:reset() for client_id, state in pairs(self.client_state) do api.nvim_buf_clear_namespace(self.bufnr, state.namespace, 0, -1) @@ -499,7 +510,7 @@ end --- in the on_win callback. The rest of the current results are saved --- in case the server supports delta requests. --- ----@private +---@package ---@param client_id integer function STHighlighter:mark_dirty(client_id) local state = self.client_state[client_id] @@ -521,7 +532,7 @@ function STHighlighter:mark_dirty(client_id) end end ----@private +---@package function STHighlighter:on_change() self:reset_timer() if self.debounce > 0 then @@ -636,6 +647,9 @@ function M.stop(bufnr, client_id) end end +--- @class STTokenRangeInspect : STTokenRange +--- @field client_id integer + --- Return the semantic token(s) at the given position. --- If called without arguments, returns the token under the cursor. --- @@ -643,13 +657,14 @@ end ---@param row integer|nil Position row (default cursor position) ---@param col integer|nil Position column (default cursor position) --- ----@return table|nil (table|nil) List of tokens at position. Each token has +---@return STTokenRangeInspect[]|nil (table|nil) List of tokens at position. Each token has --- the following fields: --- - line (integer) line number, 0-based --- - start_col (integer) start column, 0-based --- - end_col (integer) end column, 0-based --- - type (string) token type as string, e.g. "variable" --- - modifiers (table) token modifiers as a set. E.g., { static = true, readonly = true } +--- - client_id (integer) function M.get_at_pos(bufnr, row, col) if bufnr == nil or bufnr == 0 then bufnr = api.nvim_get_current_buf() @@ -665,13 +680,14 @@ function M.get_at_pos(bufnr, row, col) row, col = cursor[1] - 1, cursor[2] end - local tokens = {} + local tokens = {} --- @type STTokenRangeInspect[] for client_id, client in pairs(highlighter.client_state) do local highlights = client.current_result.highlights if highlights then local idx = lower_bound(highlights, row, 1, #highlights + 1) for i = idx, #highlights do local token = highlights[i] + --- @cast token STTokenRangeInspect if token.line > row then break diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua index ca01cdc08b..c2b5b54cb0 100644 --- a/runtime/lua/vim/lsp/sync.lua +++ b/runtime/lua/vim/lsp/sync.lua @@ -58,7 +58,7 @@ local function byte_to_utf(line, byte, offset_encoding) -- convert to 0 based indexing for str_utfindex byte = byte - 1 - local utf_idx + local utf_idx --- @type integer local _ -- Convert the byte range to utf-{8,16,32} and convert 1-based (lua) indexing to 0-based if offset_encoding == 'utf-16' then @@ -73,8 +73,11 @@ local function byte_to_utf(line, byte, offset_encoding) return utf_idx + 1 end +---@param line string +---@param offset_encoding string +---@return integer local function compute_line_length(line, offset_encoding) - local length + local length --- @type integer local _ if offset_encoding == 'utf-16' then _, length = str_utfindex(line) @@ -94,7 +97,7 @@ end ---@return integer byte_idx of first change position ---@return integer char_idx of first change position local function align_end_position(line, byte, offset_encoding) - local char + local char --- @type integer -- If on the first byte, or an empty string: the trivial case if byte == 1 or #line == 0 then char = byte @@ -120,8 +123,8 @@ local function align_end_position(line, byte, offset_encoding) end --- Finds the first line, byte, and char index of the difference between the previous and current lines buffer normalized to the previous codepoint. ----@param prev_lines table list of lines from previous buffer ----@param curr_lines table list of lines from current buffer +---@param prev_lines string[] list of lines from previous buffer +---@param curr_lines string[] list of lines from current buffer ---@param firstline integer firstline from on_lines, adjusted to 1-index ---@param lastline integer lastline from on_lines, adjusted to 1-index ---@param new_lastline integer new_lastline from on_lines, adjusted to 1-index @@ -135,14 +138,14 @@ local function compute_start_range( new_lastline, offset_encoding ) - local char_idx - local byte_idx + local char_idx --- @type integer? + local byte_idx --- @type integer? -- If firstline == lastline, no existing text is changed. All edit operations -- occur on a new line pointed to by lastline. This occurs during insertion of -- new lines(O), the new newline is inserted at the line indicated by -- new_lastline. if firstline == lastline then - local line_idx + local line_idx --- @type integer local line = prev_lines[firstline - 1] if line then line_idx = firstline - 1 @@ -343,6 +346,12 @@ end -- codeunits for utf-32 -- Line endings count here as 2 chars for \r\n (dos), 1 char for \n (unix), and 1 char for \r (mac) -- These correspond to Windows, Linux/macOS (OSX and newer), and macOS (version 9 and prior) +---@param lines string[] +---@param start_range table +---@param end_range table +---@param offset_encoding string +---@param line_ending string +---@return integer local function compute_range_length(lines, start_range, end_range, offset_encoding, line_ending) local line_ending_length = #line_ending -- Single line case @@ -351,7 +360,7 @@ local function compute_range_length(lines, start_range, end_range, offset_encodi end local start_line = lines[start_range.line_idx] - local range_length + local range_length --- @type integer if start_line and #start_line > 0 then range_length = compute_line_length(start_line, offset_encoding) - start_range.char_idx @@ -387,6 +396,7 @@ end ---@param lastline integer line to begin search in old_lines for last difference ---@param new_lastline integer line to begin search in new_lines for last difference ---@param offset_encoding string encoding requested by language server +---@param line_ending string ---@return table TextDocumentContentChangeEvent see https://microsoft.github.io/language-server-protocol/specification/#textDocumentContentChangeEvent function M.compute_diff( prev_lines, diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 32b220746f..dc8fb25563 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -2089,7 +2089,7 @@ end --- Creates a `DocumentFormattingParams` object for the current buffer and cursor position. --- ---@param options table|nil with valid `FormattingOptions` entries ----@return `DocumentFormattingParams` object +---@return lsp.DocumentFormattingParams object ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting function M.make_formatting_params(options) validate({ options = { options, 't', true } }) @@ -2228,6 +2228,6 @@ end M._get_line_byte_from_position = get_line_byte_from_position ---@nodoc -M.buf_versions = {} +M.buf_versions = {} ---@type table return M -- cgit From ddcbc5c78a492b55951cd60ba91d3d4cbf35a5c5 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Thu, 14 Dec 2023 08:38:26 -0600 Subject: docs: add comment for OSC 11 tmux passthrough (#26566) --- runtime/lua/vim/_defaults.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 2db82a04a1..b75a3dc69e 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -299,9 +299,15 @@ if tty then }) local query = '\027]11;?\007' + + -- tmux 3.3a and earlier do not query the parent terminal for background color. As of the + -- writing of this comment, 3.3a is the latest release, so a passthrough sequence is necessary. + -- The passthrough should be removed as soon as a tmux version later than 3.3a is released. + -- See: https://github.com/neovim/neovim/pull/26557 if os.getenv('TMUX') then query = string.format('\027Ptmux;%s\027\\', query:gsub('\027', '\027\027')) end + io.stdout:write(query) timer:start(1000, 0, function() -- cgit From ef38fdfdc6c84abd8ce7be02eaf8edc91ebc7917 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Thu, 14 Dec 2023 09:19:33 -0600 Subject: refactor(diagnostic): use named namespaces (#26568) Anonymous namespaces are more difficult to extend or hook into since they do not appear in the output of nvim_get_namespaces(). Use named namespaces instead. --- runtime/lua/vim/diagnostic.lua | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 0eb1ac7f15..2171ae14e6 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -877,7 +877,8 @@ M.handlers.signs = { local ns = M.get_namespace(namespace) if not ns.user_data.sign_ns then - ns.user_data.sign_ns = api.nvim_create_namespace('') + ns.user_data.sign_ns = + api.nvim_create_namespace(string.format('%s/diagnostic/signs', ns.name)) end local text = {} @@ -938,7 +939,8 @@ M.handlers.underline = { local ns = M.get_namespace(namespace) if not ns.user_data.underline_ns then - ns.user_data.underline_ns = api.nvim_create_namespace('') + ns.user_data.underline_ns = + api.nvim_create_namespace(string.format('%s/diagnostic/underline', ns.name)) end local underline_ns = ns.user_data.underline_ns @@ -1020,7 +1022,8 @@ M.handlers.virtual_text = { local ns = M.get_namespace(namespace) if not ns.user_data.virt_text_ns then - ns.user_data.virt_text_ns = api.nvim_create_namespace('') + ns.user_data.virt_text_ns = + api.nvim_create_namespace(string.format('%s/diagnostic/virtual_text', ns.name)) end local virt_text_ns = ns.user_data.virt_text_ns -- cgit From ffeb31c2f962b895bbc7111dd095e4b5ba27e88d Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Thu, 14 Dec 2023 11:37:45 -0600 Subject: fix(termcap): set 'nested' on TermResponse autocommand --- runtime/lua/vim/termcap.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/termcap.lua b/runtime/lua/vim/termcap.lua index e48657b3c2..ec29acca48 100644 --- a/runtime/lua/vim/termcap.lua +++ b/runtime/lua/vim/termcap.lua @@ -34,6 +34,7 @@ function M.query(caps, cb) local timer = assert(vim.uv.new_timer()) local id = vim.api.nvim_create_autocmd('TermResponse', { + nested = true, callback = function(args) local resp = args.data ---@type string local k, rest = resp:match('^\027P1%+r(%x+)(.*)$') -- cgit From b0e2643cb222989354a4c66c639206c84389a519 Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Thu, 14 Dec 2023 11:11:46 -0600 Subject: refactor(defaults): defer setting 'termguicolors' until after VimEnter This ensures that any OptionSet autocommands will fire when the value is changed. --- runtime/lua/vim/_defaults.lua | 67 +++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 35 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index b75a3dc69e..041a8cd669 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -175,6 +175,34 @@ for _, ui in ipairs(vim.api.nvim_list_uis()) do end if tty then + --- Set an option after startup (so that OptionSet is fired), but only if not + --- already set by the user. + --- + --- @param option string Option name + --- @param value string Option value + local function setoption(option, value) + if vim.api.nvim_get_option_info2(option, {}).was_set then + -- Don't do anything if option is already set + return + end + + -- Wait until Nvim is finished starting to set the option to ensure the + -- OptionSet event fires. + if vim.v.vim_did_enter == 1 then + if vim.o[option] ~= value then + vim.o[option] = value + end + else + vim.api.nvim_create_autocmd('VimEnter', { + once = true, + nested = true, + callback = function() + setoption(option, value) + end, + }) + end + end + --- Guess value of 'background' based on terminal color. --- --- We write Operating System Command (OSC) 11 to the terminal to request the @@ -253,30 +281,6 @@ if tty then local timer = assert(vim.uv.new_timer()) - ---@param bg string New value of the 'background' option - local function setbg(bg) - if vim.api.nvim_get_option_info2('background', {}).was_set then - -- Don't do anything if 'background' is already set - return - end - - -- Wait until Nvim is finished starting to set 'background' to ensure the - -- OptionSet event fires. - if vim.v.vim_did_enter == 1 then - if vim.o.background ~= bg then - vim.o.background = bg - end - else - vim.api.nvim_create_autocmd('VimEnter', { - once = true, - nested = true, - callback = function() - setbg(bg) - end, - }) - end - end - local id = vim.api.nvim_create_autocmd('TermResponse', { nested = true, callback = function(args) @@ -290,7 +294,7 @@ if tty then if rr and gg and bb then local luminance = (0.299 * rr) + (0.587 * gg) + (0.114 * bb) local bg = luminance < 0.5 and 'dark' or 'light' - setbg(bg) + setoption('background', bg) end return true @@ -331,15 +335,8 @@ if tty then do if tty.rgb then -- The TUI was able to determine truecolor support - vim.o.termguicolors = true + setoption('termguicolors', true) else - --- Enable 'termguicolors', but only if it was not already set by the user. - local function settgc() - if not vim.api.nvim_get_option_info2('termguicolors', {}).was_set then - vim.o.termguicolors = true - end - end - local caps = {} ---@type table require('vim.termcap').query({ 'Tc', 'RGB', 'setrgbf', 'setrgbb' }, function(cap, found) if not found then @@ -348,7 +345,7 @@ if tty then caps[cap] = true if caps.Tc or caps.RGB or (caps.setrgbf and caps.setrgbb) then - settgc() + setoption('termguicolors', true) end end) @@ -395,7 +392,7 @@ if tty then and tonumber(params[#params - 1]) == g and tonumber(params[#params]) == b then - settgc() + setoption('termguicolors', true) end return true -- cgit From 165e5ececc25ce2d705efdd8ee6c8406884bf898 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 15 Dec 2023 06:42:29 +0800 Subject: vim-patch:17dca3cb97cd (#26584) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit runtime(doc): grammar & typo fixes closes: vim/vim#13654 https://github.com/vim/vim/commit/17dca3cb97cdd7835e334b990565c8c0b93b1284 Co-authored-by: Dominique Pellé --- runtime/lua/vim/_meta/vimfn.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 7234b813b6..ead5d8d13b 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -6156,9 +6156,9 @@ function vim.fn.prevnonblank(lnum) end --- Date: Fri, 15 Dec 2023 16:35:55 -0600 Subject: refactor(defaults): always set options, even if value hasn't changed (#26595) Comparing against the old value before setting matched the original C implementation, but there is no reason to use this restriction. In particular, this inhibits using OptionSet to determine when the option was set. If users need to handle a case where the option _changed_, it is easy to do so in an OptionSet autocommand using v:option_new and v:option_old (and friends). --- runtime/lua/vim/_defaults.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 041a8cd669..2627cbcd0d 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -189,9 +189,7 @@ if tty then -- Wait until Nvim is finished starting to set the option to ensure the -- OptionSet event fires. if vim.v.vim_did_enter == 1 then - if vim.o[option] ~= value then - vim.o[option] = value - end + vim.o[option] = value else vim.api.nvim_create_autocmd('VimEnter', { once = true, -- cgit From e38027ef69f75653ee953b16ebf4a8652a3fb748 Mon Sep 17 00:00:00 2001 From: mathew Date: Tue, 15 Aug 2023 18:47:14 +0800 Subject: feat(ui): completeopt support popup like vim --- runtime/lua/vim/_meta/api.lua | 10 ++++++++++ runtime/lua/vim/_meta/api_keysets.lua | 3 +++ runtime/lua/vim/_meta/options.lua | 4 ++++ runtime/lua/vim/_meta/vimfn.lua | 2 ++ 4 files changed, 19 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 231e1c3404..c8afbd58dd 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -773,6 +773,16 @@ function vim.api.nvim_command(command) end --- @return string function vim.api.nvim_command_output(command) end +--- Set info for the completion candidate index. if the info was shown in a +--- window, then the window and buffer ids are returned for further +--- customization. If the text was not shown, an empty dict is returned. +--- +--- @param index integer the completion candidate index +--- @param opts vim.api.keyset.complete_set Optional parameters. +--- • info: (string) info text. +--- @return table +function vim.api.nvim_complete_set(index, opts) end + --- Create or get an autocommand group `autocmd-groups`. --- To get an existing group id, do: --- diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index f64cdb8afd..4ec8b03d30 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -68,6 +68,9 @@ error('Cannot require a meta file') --- @class vim.api.keyset.cmd_opts --- @field output? boolean +--- @class vim.api.keyset.complete_set +--- @field info? string + --- @class vim.api.keyset.context --- @field types? any[] diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 5e65ca6b1b..c908d7ae54 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -1061,6 +1061,10 @@ vim.bo.cfu = vim.bo.completefunc --- select one from the menu. Only works in combination with --- "menu" or "menuone". --- +--- popup Show extra information about the currently selected +--- completion in a popup window. Only works in combination +--- with "menu" or "menuone". Overrides "preview". +--- --- @type string vim.o.completeopt = "menu,preview" vim.o.cot = vim.o.completeopt diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index ead5d8d13b..59d9836688 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -1024,6 +1024,8 @@ function vim.fn.complete_check() end --- no item is selected when using the or --- keys) --- inserted Inserted string. [NOT IMPLEMENTED YET] +--- preview_winid Info floating preview window id. +--- preview_bufnr Info floating preview buffer id. --- --- *complete_info_mode* --- mode values are: -- cgit From 69f5f0e20e81ef3b6cb5ea011eda024e6e277acf Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 16 Dec 2023 15:03:22 +0100 Subject: vim-patch:82f19734bfcb runtime(doc): remove deprecation warning for gdefault Deprecated can be misunderstood as being slated for removal; slightly change wording to be clearer. https://github.com/vim/vim/commit/82f19734bfcbddbaee8d5d837f7b7a7119366020 Co-authored-by: dundargoc --- runtime/lua/vim/_meta/options.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index c908d7ae54..f52cea9900 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -2595,9 +2595,9 @@ vim.go.fs = vim.go.fsync --- :s///g subst. one subst. all --- :s///gg subst. all subst. one --- ---- DEPRECATED: Setting this option may break plugins that are not aware ---- of this option. Also, many users get confused that adding the /g flag ---- has the opposite effect of that it normally does. +--- NOTE: Setting this option may break plugins that rely on the default +--- behavior of the 'g' flag. This will also make the 'g' flag have the +--- opposite effect of that documented in `:s_g`. --- --- @type boolean vim.o.gdefault = false -- cgit From 8fb7419d7c5e2df3b792d18fa56f973088e69be2 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Sat, 16 Dec 2023 11:18:45 -0600 Subject: refactor: only reload colorscheme if &bg changed (#26598) Currently, setting &bg at all re-initializes highlights and reloads the active colorscheme, even if the actual value of &bg has not changed. With https://github.com/neovim/neovim/pull/26595 this causes a regression since &bg is set unconditionally based on the value detected from the terminal. Instead, only reload the colorscheme if the actual value of &bg has changed. --- runtime/lua/vim/_meta/options.lua | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index f52cea9900..e63c5bb972 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -191,7 +191,7 @@ vim.go.awa = vim.go.autowriteall --- See `:hi-normal` if you want to set the background color explicitly. --- *g:colors_name* --- When a color scheme is loaded (the "g:colors_name" variable is set) ---- setting 'background' will cause the color scheme to be reloaded. If +--- changing 'background' will cause the color scheme to be reloaded. If --- the color scheme adjusts to the value of 'background' this will work. --- However, if the color scheme sets 'background' itself the effect may --- be undone. First delete the "g:colors_name" variable when needed. @@ -203,13 +203,9 @@ vim.go.awa = vim.go.autowriteall --- : set background=dark --- :endif --- ``` ---- When this option is set, the default settings for the highlight groups +--- When this option is changed, the default settings for the highlight groups --- will change. To use other settings, place ":highlight" commands AFTER --- the setting of the 'background' option. ---- This option is also used in the "$VIMRUNTIME/syntax/syntax.vim" file ---- to select the colors for syntax highlighting. After changing this ---- option, you must load syntax.vim again to see the result. This can be ---- done with ":syntax on". --- --- @type string vim.o.background = "dark" -- cgit From 5a2536de0c4beae4eba50a0d2868983c1690ecc7 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sun, 17 Dec 2023 09:54:38 +0000 Subject: refactor(lsp): move changetracking to separate file (#26577) * refactor(lsp): move changetracking to separate file - Prefixed changetracking types with `vim.lsp.` * fixup!: make _reset_timer a local function * fixup!: remove @private annotations * fixup!: changetracking.lua -> _changetracking.lua * fixup! types * fixup! add send_changes_for_group --- runtime/lua/vim/lsp.lua | 364 +------------------------------ runtime/lua/vim/lsp/_changetracking.lua | 373 ++++++++++++++++++++++++++++++++ runtime/lua/vim/lsp/sync.lua | 2 +- 3 files changed, 383 insertions(+), 356 deletions(-) create mode 100644 runtime/lua/vim/lsp/_changetracking.lua (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 31aacd668b..6476335213 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -5,7 +5,7 @@ local lsp_rpc = require('vim.lsp.rpc') local protocol = require('vim.lsp.protocol') local ms = protocol.Methods local util = require('vim.lsp.util') -local sync = require('vim.lsp.sync') +local changetracking = require('vim.lsp._changetracking') local semantic_tokens = require('vim.lsp.semantic_tokens') local api = vim.api @@ -132,9 +132,10 @@ local format_line_ending = { ['mac'] = '\r', } +---@private ---@param bufnr (number) ---@return string -local function buf_get_line_ending(bufnr) +function lsp._buf_get_line_ending(bufnr) return format_line_ending[vim.bo[bufnr].fileformat] or '\n' end @@ -305,12 +306,13 @@ local function validate_client_config(config) return cmd, cmd_args, offset_encoding end +---@private --- Returns full text of buffer {bufnr} as a string. --- ---@param bufnr (number) Buffer handle, or 0 for current. ---@return string # Buffer text as string. -local function buf_get_full_text(bufnr) - local line_ending = buf_get_line_ending(bufnr) +function lsp._buf_get_full_text(bufnr) + local line_ending = lsp._buf_get_line_ending(bufnr) local text = table.concat(nvim_buf_get_lines(bufnr, 0, -1, true), line_ending) if vim.bo[bufnr].eol then text = text .. line_ending @@ -338,354 +340,6 @@ local function once(fn) end end -local changetracking = {} -do - ---@private - --- - --- LSP has 3 different sync modes: - --- - None (Servers will read the files themselves when needed) - --- - Full (Client sends the full buffer content on updates) - --- - Incremental (Client sends only the changed parts) - --- - --- Changes are tracked per buffer. - --- A buffer can have multiple clients attached and each client needs to send the changes - --- To minimize the amount of changesets to compute, computation is grouped: - --- - --- None: One group for all clients - --- Full: One group for all clients - --- Incremental: One group per `offset_encoding` - --- - --- Sending changes can be debounced per buffer. To simplify the implementation the - --- smallest debounce interval is used and we don't group clients by different intervals. - --- - --- @class CTGroup - --- @field sync_kind integer TextDocumentSyncKind, considers config.flags.allow_incremental_sync - --- @field offset_encoding "utf-8"|"utf-16"|"utf-32" - --- - --- @class CTBufferState - --- @field name string name of the buffer - --- @field lines string[] snapshot of buffer lines from last didChange - --- @field lines_tmp string[] - --- @field pending_changes table[] List of debounced changes in incremental sync mode - --- @field timer nil|uv.uv_timer_t uv_timer - --- @field last_flush nil|number uv.hrtime of the last flush/didChange-notification - --- @field needs_flush boolean true if buffer updates haven't been sent to clients/servers yet - --- @field refs integer how many clients are using this group - --- - --- @class CTGroupState - --- @field buffers table - --- @field debounce integer debounce duration in ms - --- @field clients table clients using this state. {client_id, client} - - ---@param group CTGroup - ---@return string - local function group_key(group) - if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then - return tostring(group.sync_kind) .. '\0' .. group.offset_encoding - end - return tostring(group.sync_kind) - end - - ---@private - ---@type table - local state_by_group = setmetatable({}, { - __index = function(tbl, k) - return rawget(tbl, group_key(k)) - end, - __newindex = function(tbl, k, v) - rawset(tbl, group_key(k), v) - end, - }) - - ---@param client lsp.Client - ---@return CTGroup - local function get_group(client) - local allow_inc_sync = if_nil(client.config.flags.allow_incremental_sync, true) - local change_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'change') - local sync_kind = change_capability or protocol.TextDocumentSyncKind.None - if not allow_inc_sync and change_capability == protocol.TextDocumentSyncKind.Incremental then - sync_kind = protocol.TextDocumentSyncKind.Full --[[@as integer]] - end - return { - sync_kind = sync_kind, - offset_encoding = client.offset_encoding, - } - end - - ---@param state CTBufferState - local function incremental_changes(state, encoding, bufnr, firstline, lastline, new_lastline) - local prev_lines = state.lines - local curr_lines = state.lines_tmp - - local changed_lines = nvim_buf_get_lines(bufnr, firstline, new_lastline, true) - for i = 1, firstline do - curr_lines[i] = prev_lines[i] - end - for i = firstline + 1, new_lastline do - curr_lines[i] = changed_lines[i - firstline] - end - for i = lastline + 1, #prev_lines do - curr_lines[i - lastline + new_lastline] = prev_lines[i] - end - if tbl_isempty(curr_lines) then - -- Can happen when deleting the entire contents of a buffer, see https://github.com/neovim/neovim/issues/16259. - curr_lines[1] = '' - end - - local line_ending = buf_get_line_ending(bufnr) - local incremental_change = sync.compute_diff( - state.lines, - curr_lines, - firstline, - lastline, - new_lastline, - encoding, - line_ending - ) - - -- Double-buffering of lines tables is used to reduce the load on the garbage collector. - -- At this point the prev_lines table is useless, but its internal storage has already been allocated, - -- so let's keep it around for the next didChange event, in which it will become the next - -- curr_lines table. Note that setting elements to nil doesn't actually deallocate slots in the - -- internal storage - it merely marks them as free, for the GC to deallocate them. - for i in ipairs(prev_lines) do - prev_lines[i] = nil - end - state.lines = curr_lines - state.lines_tmp = prev_lines - - return incremental_change - end - - ---@private - function changetracking.init(client, bufnr) - assert(client.offset_encoding, 'lsp client must have an offset_encoding') - local group = get_group(client) - local state = state_by_group[group] - if state then - state.debounce = math.min(state.debounce, client.config.flags.debounce_text_changes or 150) - state.clients[client.id] = client - else - state = { - buffers = {}, - debounce = client.config.flags.debounce_text_changes or 150, - clients = { - [client.id] = client, - }, - } - state_by_group[group] = state - end - local buf_state = state.buffers[bufnr] - if buf_state then - buf_state.refs = buf_state.refs + 1 - else - buf_state = { - name = api.nvim_buf_get_name(bufnr), - lines = {}, - lines_tmp = {}, - pending_changes = {}, - needs_flush = false, - refs = 1, - } - state.buffers[bufnr] = buf_state - if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then - buf_state.lines = nvim_buf_get_lines(bufnr, 0, -1, true) - end - end - end - - ---@private - function changetracking._get_and_set_name(client, bufnr, name) - local state = state_by_group[get_group(client)] or {} - local buf_state = (state.buffers or {})[bufnr] - local old_name = buf_state.name - buf_state.name = name - return old_name - end - - ---@private - function changetracking.reset_buf(client, bufnr) - changetracking.flush(client, bufnr) - local state = state_by_group[get_group(client)] - if not state then - return - end - assert(state.buffers, 'CTGroupState must have buffers') - local buf_state = state.buffers[bufnr] - buf_state.refs = buf_state.refs - 1 - assert(buf_state.refs >= 0, 'refcount on buffer state must not get negative') - if buf_state.refs == 0 then - state.buffers[bufnr] = nil - changetracking._reset_timer(buf_state) - end - end - - ---@private - function changetracking.reset(client) - local state = state_by_group[get_group(client)] - if not state then - return - end - state.clients[client.id] = nil - if vim.tbl_count(state.clients) == 0 then - for _, buf_state in pairs(state.buffers) do - changetracking._reset_timer(buf_state) - end - state.buffers = {} - end - end - - -- Adjust debounce time by taking time of last didChange notification into - -- consideration. If the last didChange happened more than `debounce` time ago, - -- debounce can be skipped and otherwise maybe reduced. - -- - -- This turns the debounce into a kind of client rate limiting - -- - ---@param debounce integer - ---@param buf_state CTBufferState - ---@return number - local function next_debounce(debounce, buf_state) - if debounce == 0 then - return 0 - end - local ns_to_ms = 0.000001 - if not buf_state.last_flush then - return debounce - end - local now = uv.hrtime() - local ms_since_last_flush = (now - buf_state.last_flush) * ns_to_ms - return math.max(debounce - ms_since_last_flush, 0) - end - - ---@param bufnr integer - ---@param sync_kind integer protocol.TextDocumentSyncKind - ---@param state CTGroupState - ---@param buf_state CTBufferState - local function send_changes(bufnr, sync_kind, state, buf_state) - if not buf_state.needs_flush then - return - end - buf_state.last_flush = uv.hrtime() - buf_state.needs_flush = false - - if not api.nvim_buf_is_valid(bufnr) then - buf_state.pending_changes = {} - return - end - - local changes --- @type lsp.TextDocumentContentChangeEvent[] - if sync_kind == protocol.TextDocumentSyncKind.None then - return - elseif sync_kind == protocol.TextDocumentSyncKind.Incremental then - changes = buf_state.pending_changes - buf_state.pending_changes = {} - else - changes = { - { text = buf_get_full_text(bufnr) }, - } - end - local uri = vim.uri_from_bufnr(bufnr) - for _, client in pairs(state.clients) do - if not client.is_stopped() and lsp.buf_is_attached(bufnr, client.id) then - client.notify(ms.textDocument_didChange, { - textDocument = { - uri = uri, - version = util.buf_versions[bufnr], - }, - contentChanges = changes, - }) - end - end - end - - ---@private - function changetracking.send_changes(bufnr, firstline, lastline, new_lastline) - local groups = {} ---@type table - for _, client in pairs(lsp.get_clients({ bufnr = bufnr })) do - local group = get_group(client) - groups[group_key(group)] = group - end - for _, group in pairs(groups) do - local state = state_by_group[group] - if not state then - error( - string.format( - 'changetracking.init must have been called for all LSP clients. group=%s states=%s', - vim.inspect(group), - vim.inspect(vim.tbl_keys(state_by_group)) - ) - ) - end - local buf_state = state.buffers[bufnr] - buf_state.needs_flush = true - changetracking._reset_timer(buf_state) - local debounce = next_debounce(state.debounce, buf_state) - if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then - -- This must be done immediately and cannot be delayed - -- The contents would further change and startline/endline may no longer fit - local changes = incremental_changes( - buf_state, - group.offset_encoding, - bufnr, - firstline, - lastline, - new_lastline - ) - table.insert(buf_state.pending_changes, changes) - end - if debounce == 0 then - send_changes(bufnr, group.sync_kind, state, buf_state) - else - local timer = assert(uv.new_timer(), 'Must be able to create timer') - buf_state.timer = timer - timer:start( - debounce, - 0, - vim.schedule_wrap(function() - changetracking._reset_timer(buf_state) - send_changes(bufnr, group.sync_kind, state, buf_state) - end) - ) - end - end - end - - ---@private - ---@param buf_state CTBufferState - function changetracking._reset_timer(buf_state) - local timer = buf_state.timer - if timer then - buf_state.timer = nil - if not timer:is_closing() then - timer:stop() - timer:close() - end - end - end - - --- Flushes any outstanding change notification. - ---@private - ---@param client lsp.Client - ---@param bufnr? integer - function changetracking.flush(client, bufnr) - local group = get_group(client) - local state = state_by_group[group] - if not state then - return - end - if bufnr then - local buf_state = state.buffers[bufnr] or {} - changetracking._reset_timer(buf_state) - send_changes(bufnr, group.sync_kind, state, buf_state) - else - for buf, buf_state in pairs(state.buffers) do - changetracking._reset_timer(buf_state) - send_changes(buf, group.sync_kind, state, buf_state) - end - end - end -end - --- Default handler for the 'textDocument/didOpen' LSP notification. --- ---@param bufnr integer Number of the buffer, or 0 for current @@ -705,7 +359,7 @@ local function text_document_did_open_handler(bufnr, client) version = 0, uri = vim.uri_from_bufnr(bufnr), languageId = client.config.get_language_id(bufnr, filetype), - text = buf_get_full_text(bufnr), + text = lsp._buf_get_full_text(bufnr), }, } client.notify(ms.textDocument_didOpen, params) @@ -1792,7 +1446,7 @@ end local function text_document_did_save_handler(bufnr) bufnr = resolve_bufnr(bufnr) local uri = vim.uri_from_bufnr(bufnr) - local text = once(buf_get_full_text) + local text = once(lsp._buf_get_full_text) for _, client in ipairs(lsp.get_clients({ bufnr = bufnr })) do local name = api.nvim_buf_get_name(bufnr) local old_name = changetracking._get_and_set_name(client, bufnr, name) @@ -1807,7 +1461,7 @@ local function text_document_did_save_handler(bufnr) version = 0, uri = uri, languageId = client.config.get_language_id(bufnr, vim.bo[bufnr].filetype), - text = buf_get_full_text(bufnr), + text = lsp._buf_get_full_text(bufnr), }, }) util.buf_versions[bufnr] = 0 diff --git a/runtime/lua/vim/lsp/_changetracking.lua b/runtime/lua/vim/lsp/_changetracking.lua new file mode 100644 index 0000000000..67c74f069d --- /dev/null +++ b/runtime/lua/vim/lsp/_changetracking.lua @@ -0,0 +1,373 @@ +local protocol = require('vim.lsp.protocol') +local sync = require('vim.lsp.sync') +local util = require('vim.lsp.util') + +local api = vim.api +local uv = vim.uv + +local M = {} + +--- LSP has 3 different sync modes: +--- - None (Servers will read the files themselves when needed) +--- - Full (Client sends the full buffer content on updates) +--- - Incremental (Client sends only the changed parts) +--- +--- Changes are tracked per buffer. +--- A buffer can have multiple clients attached and each client needs to send the changes +--- To minimize the amount of changesets to compute, computation is grouped: +--- +--- None: One group for all clients +--- Full: One group for all clients +--- Incremental: One group per `offset_encoding` +--- +--- Sending changes can be debounced per buffer. To simplify the implementation the +--- smallest debounce interval is used and we don't group clients by different intervals. +--- +--- @class vim.lsp.CTGroup +--- @field sync_kind integer TextDocumentSyncKind, considers config.flags.allow_incremental_sync +--- @field offset_encoding "utf-8"|"utf-16"|"utf-32" +--- +--- @class vim.lsp.CTBufferState +--- @field name string name of the buffer +--- @field lines string[] snapshot of buffer lines from last didChange +--- @field lines_tmp string[] +--- @field pending_changes table[] List of debounced changes in incremental sync mode +--- @field timer uv.uv_timer_t? uv_timer +--- @field last_flush nil|number uv.hrtime of the last flush/didChange-notification +--- @field needs_flush boolean true if buffer updates haven't been sent to clients/servers yet +--- @field refs integer how many clients are using this group +--- +--- @class vim.lsp.CTGroupState +--- @field buffers table +--- @field debounce integer debounce duration in ms +--- @field clients table clients using this state. {client_id, client} + +---@param group vim.lsp.CTGroup +---@return string +local function group_key(group) + if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then + return tostring(group.sync_kind) .. '\0' .. group.offset_encoding + end + return tostring(group.sync_kind) +end + +---@type table +local state_by_group = setmetatable({}, { + __index = function(tbl, k) + return rawget(tbl, group_key(k)) + end, + __newindex = function(tbl, k, v) + rawset(tbl, group_key(k), v) + end, +}) + +---@param client lsp.Client +---@return vim.lsp.CTGroup +local function get_group(client) + local allow_inc_sync = vim.F.if_nil(client.config.flags.allow_incremental_sync, true) + local change_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'change') + local sync_kind = change_capability or protocol.TextDocumentSyncKind.None + if not allow_inc_sync and change_capability == protocol.TextDocumentSyncKind.Incremental then + sync_kind = protocol.TextDocumentSyncKind.Full --[[@as integer]] + end + return { + sync_kind = sync_kind, + offset_encoding = client.offset_encoding, + } +end + +---@param state vim.lsp.CTBufferState +---@param encoding string +---@param bufnr integer +---@param firstline integer +---@param lastline integer +---@param new_lastline integer +---@return lsp.TextDocumentContentChangeEvent +local function incremental_changes(state, encoding, bufnr, firstline, lastline, new_lastline) + local prev_lines = state.lines + local curr_lines = state.lines_tmp + + local changed_lines = api.nvim_buf_get_lines(bufnr, firstline, new_lastline, true) + for i = 1, firstline do + curr_lines[i] = prev_lines[i] + end + for i = firstline + 1, new_lastline do + curr_lines[i] = changed_lines[i - firstline] + end + for i = lastline + 1, #prev_lines do + curr_lines[i - lastline + new_lastline] = prev_lines[i] + end + if vim.tbl_isempty(curr_lines) then + -- Can happen when deleting the entire contents of a buffer, see https://github.com/neovim/neovim/issues/16259. + curr_lines[1] = '' + end + + local line_ending = vim.lsp._buf_get_line_ending(bufnr) + local incremental_change = sync.compute_diff( + state.lines, + curr_lines, + firstline, + lastline, + new_lastline, + encoding, + line_ending + ) + + -- Double-buffering of lines tables is used to reduce the load on the garbage collector. + -- At this point the prev_lines table is useless, but its internal storage has already been allocated, + -- so let's keep it around for the next didChange event, in which it will become the next + -- curr_lines table. Note that setting elements to nil doesn't actually deallocate slots in the + -- internal storage - it merely marks them as free, for the GC to deallocate them. + for i in ipairs(prev_lines) do + prev_lines[i] = nil + end + state.lines = curr_lines + state.lines_tmp = prev_lines + + return incremental_change +end + +---@param client lsp.Client +---@param bufnr integer +function M.init(client, bufnr) + assert(client.offset_encoding, 'lsp client must have an offset_encoding') + local group = get_group(client) + local state = state_by_group[group] + if state then + state.debounce = math.min(state.debounce, client.config.flags.debounce_text_changes or 150) + state.clients[client.id] = client + else + state = { + buffers = {}, + debounce = client.config.flags.debounce_text_changes or 150, + clients = { + [client.id] = client, + }, + } + state_by_group[group] = state + end + local buf_state = state.buffers[bufnr] + if buf_state then + buf_state.refs = buf_state.refs + 1 + else + buf_state = { + name = api.nvim_buf_get_name(bufnr), + lines = {}, + lines_tmp = {}, + pending_changes = {}, + needs_flush = false, + refs = 1, + } + state.buffers[bufnr] = buf_state + if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then + buf_state.lines = api.nvim_buf_get_lines(bufnr, 0, -1, true) + end + end +end + +--- @param client lsp.Client +--- @param bufnr integer +--- @param name string +--- @return string +function M._get_and_set_name(client, bufnr, name) + local state = state_by_group[get_group(client)] or {} + local buf_state = (state.buffers or {})[bufnr] + local old_name = buf_state.name + buf_state.name = name + return old_name +end + +---@param buf_state vim.lsp.CTBufferState +local function reset_timer(buf_state) + local timer = buf_state.timer + if timer then + buf_state.timer = nil + if not timer:is_closing() then + timer:stop() + timer:close() + end + end +end + +--- @param client lsp.Client +--- @param bufnr integer +function M.reset_buf(client, bufnr) + M.flush(client, bufnr) + local state = state_by_group[get_group(client)] + if not state then + return + end + assert(state.buffers, 'CTGroupState must have buffers') + local buf_state = state.buffers[bufnr] + buf_state.refs = buf_state.refs - 1 + assert(buf_state.refs >= 0, 'refcount on buffer state must not get negative') + if buf_state.refs == 0 then + state.buffers[bufnr] = nil + reset_timer(buf_state) + end +end + +--- @param client lsp.Client +function M.reset(client) + local state = state_by_group[get_group(client)] + if not state then + return + end + state.clients[client.id] = nil + if vim.tbl_count(state.clients) == 0 then + for _, buf_state in pairs(state.buffers) do + reset_timer(buf_state) + end + state.buffers = {} + end +end + +-- Adjust debounce time by taking time of last didChange notification into +-- consideration. If the last didChange happened more than `debounce` time ago, +-- debounce can be skipped and otherwise maybe reduced. +-- +-- This turns the debounce into a kind of client rate limiting +-- +---@param debounce integer +---@param buf_state vim.lsp.CTBufferState +---@return number +local function next_debounce(debounce, buf_state) + if debounce == 0 then + return 0 + end + local ns_to_ms = 0.000001 + if not buf_state.last_flush then + return debounce + end + local now = uv.hrtime() + local ms_since_last_flush = (now - buf_state.last_flush) * ns_to_ms + return math.max(debounce - ms_since_last_flush, 0) +end + +---@param bufnr integer +---@param sync_kind integer protocol.TextDocumentSyncKind +---@param state vim.lsp.CTGroupState +---@param buf_state vim.lsp.CTBufferState +local function send_changes(bufnr, sync_kind, state, buf_state) + if not buf_state.needs_flush then + return + end + buf_state.last_flush = uv.hrtime() + buf_state.needs_flush = false + + if not api.nvim_buf_is_valid(bufnr) then + buf_state.pending_changes = {} + return + end + + local changes --- @type lsp.TextDocumentContentChangeEvent[] + if sync_kind == protocol.TextDocumentSyncKind.None then + return + elseif sync_kind == protocol.TextDocumentSyncKind.Incremental then + changes = buf_state.pending_changes + buf_state.pending_changes = {} + else + changes = { + { text = vim.lsp._buf_get_full_text(bufnr) }, + } + end + local uri = vim.uri_from_bufnr(bufnr) + for _, client in pairs(state.clients) do + if not client.is_stopped() and vim.lsp.buf_is_attached(bufnr, client.id) then + client.notify(protocol.Methods.textDocument_didChange, { + textDocument = { + uri = uri, + version = util.buf_versions[bufnr], + }, + contentChanges = changes, + }) + end + end +end + +--- @param bufnr integer +--- @param firstline integer +--- @param lastline integer +--- @param new_lastline integer +--- @param group vim.lsp.CTGroup +local function send_changes_for_group(bufnr, firstline, lastline, new_lastline, group) + local state = state_by_group[group] + if not state then + error( + string.format( + 'changetracking.init must have been called for all LSP clients. group=%s states=%s', + vim.inspect(group), + vim.inspect(vim.tbl_keys(state_by_group)) + ) + ) + end + local buf_state = state.buffers[bufnr] + buf_state.needs_flush = true + reset_timer(buf_state) + local debounce = next_debounce(state.debounce, buf_state) + if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then + -- This must be done immediately and cannot be delayed + -- The contents would further change and startline/endline may no longer fit + local changes = incremental_changes( + buf_state, + group.offset_encoding, + bufnr, + firstline, + lastline, + new_lastline + ) + table.insert(buf_state.pending_changes, changes) + end + if debounce == 0 then + send_changes(bufnr, group.sync_kind, state, buf_state) + else + local timer = assert(uv.new_timer(), 'Must be able to create timer') + buf_state.timer = timer + timer:start( + debounce, + 0, + vim.schedule_wrap(function() + reset_timer(buf_state) + send_changes(bufnr, group.sync_kind, state, buf_state) + end) + ) + end +end + +--- @param bufnr integer +--- @param firstline integer +--- @param lastline integer +--- @param new_lastline integer +function M.send_changes(bufnr, firstline, lastline, new_lastline) + local groups = {} ---@type table + for _, client in pairs(vim.lsp.get_clients({ bufnr = bufnr })) do + local group = get_group(client) + groups[group_key(group)] = group + end + for _, group in pairs(groups) do + send_changes_for_group(bufnr, firstline, lastline, new_lastline, group) + end +end + +--- Flushes any outstanding change notification. +---@param client lsp.Client +---@param bufnr? integer +function M.flush(client, bufnr) + local group = get_group(client) + local state = state_by_group[group] + if not state then + return + end + if bufnr then + local buf_state = state.buffers[bufnr] or {} + reset_timer(buf_state) + send_changes(bufnr, group.sync_kind, state, buf_state) + else + for buf, buf_state in pairs(state.buffers) do + reset_timer(buf_state) + send_changes(buf, group.sync_kind, state, buf_state) + end + end +end + +return M diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua index c2b5b54cb0..7ebe2dbb88 100644 --- a/runtime/lua/vim/lsp/sync.lua +++ b/runtime/lua/vim/lsp/sync.lua @@ -397,7 +397,7 @@ end ---@param new_lastline integer line to begin search in new_lines for last difference ---@param offset_encoding string encoding requested by language server ---@param line_ending string ----@return table TextDocumentContentChangeEvent see https://microsoft.github.io/language-server-protocol/specification/#textDocumentContentChangeEvent +---@return lsp.TextDocumentContentChangeEvent : see https://microsoft.github.io/language-server-protocol/specification/#textDocumentContentChangeEvent function M.compute_diff( prev_lines, curr_lines, -- cgit From c0cb1e8e9437b738c8d3232ec4594113d2221bb2 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Sun, 17 Dec 2023 15:25:15 +0900 Subject: perf(treesitter): filter out trees outside the visible range early Problem: Treesitter highlighter's on_line was iterating all the parsed trees, which can be quite a lot when injection is used. This may slow down scrolling and cursor movement in big files with many comment injections (e.g., lsp/_meta/protocol.lua). Solution: In on_win, collect trees inside the visible range, and use them in on_line. NOTE: This optimization depends on the correctness of on_win's botline_guess parameter (i.e., it's always greater than or equal to the line numbers passed to on_line). The documentation does not guarantee this, but I have never noticed a problem so far. --- runtime/lua/vim/treesitter/highlighter.lua | 74 +++++++++++++++++++----------- 1 file changed, 47 insertions(+), 27 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 496193c6ed..17543bc787 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -5,14 +5,16 @@ local Range = require('vim.treesitter._range') ---@alias TSHlIter fun(end_line: integer|nil): integer, TSNode, TSMetadata ---@class TSHighlightState +---@field tstree TSTree ---@field next_row integer ---@field iter TSHlIter|nil +---@field highlighter_query TSHighlighterQuery ---@class TSHighlighter ---@field active table ---@field bufnr integer ---@field orig_spelloptions string ----@field _highlight_states table +---@field _highlight_states TSHighlightState[] ---@field _queries table ---@field tree LanguageTree ---@field redraw_count integer @@ -157,18 +159,47 @@ function TSHighlighter:destroy() end end ----@package ----@param tstree TSTree ----@return TSHighlightState -function TSHighlighter:get_highlight_state(tstree) - if not self._highlight_states[tstree] then - self._highlight_states[tstree] = { +---@param srow integer +---@param erow integer exclusive +---@private +function TSHighlighter:prepare_highlight_states(srow, erow) + self.tree:for_each_tree(function(tstree, tree) + if not tstree then + return + end + + local root_node = tstree:root() + local root_start_row, _, root_end_row, _ = root_node:range() + + -- Only worry about trees within the visible range + if root_start_row > erow or root_end_row < srow then + return + end + + local highlighter_query = self:get_query(tree:lang()) + + -- Some injected languages may not have highlight queries. + if not highlighter_query:query() then + return + end + + -- _highlight_states should be a list so that the highlights are added in the same order as + -- for_each_tree traversal. This ensures that parents' highlight don't override children's. + table.insert(self._highlight_states, { + tstree = tstree, next_row = 0, iter = nil, - } - end + highlighter_query = highlighter_query, + }) + end) +end - return self._highlight_states[tstree] +---@param fn fun(state: TSHighlightState) +---@package +function TSHighlighter:for_each_highlight_state(fn) + for _, state in ipairs(self._highlight_states) do + fn(state) + end end ---@private @@ -214,12 +245,8 @@ end ---@param line integer ---@param is_spell_nav boolean local function on_line_impl(self, buf, line, is_spell_nav) - self.tree:for_each_tree(function(tstree, tree) - if not tstree then - return - end - - local root_node = tstree:root() + self:for_each_highlight_state(function(state) + local root_node = state.tstree:root() local root_start_row, _, root_end_row, _ = root_node:range() -- Only worry about trees within the line range @@ -227,17 +254,9 @@ local function on_line_impl(self, buf, line, is_spell_nav) return end - local state = self:get_highlight_state(tstree) - local highlighter_query = self:get_query(tree:lang()) - - -- Some injected languages may not have highlight queries. - if not highlighter_query:query() then - return - end - if state.iter == nil or state.next_row < line then state.iter = - highlighter_query:query():iter_captures(root_node, self.bufnr, line, root_end_row + 1) + state.highlighter_query:query():iter_captures(root_node, self.bufnr, line, root_end_row + 1) end while line >= state.next_row do @@ -250,9 +269,9 @@ local function on_line_impl(self, buf, line, is_spell_nav) local start_row, start_col, end_row, end_col = Range.unpack4(range) if capture then - local hl = highlighter_query.hl_cache[capture] + local hl = state.highlighter_query.hl_cache[capture] - local capture_name = highlighter_query:query().captures[capture] + local capture_name = state.highlighter_query:query().captures[capture] local spell = nil ---@type boolean? if capture_name == 'spell' then spell = true @@ -327,6 +346,7 @@ function TSHighlighter._on_win(_, _win, buf, topline, botline) end self.tree:parse({ topline, botline + 1 }) self:reset_highlight_state() + self:prepare_highlight_states(topline, botline + 1) self.redraw_count = self.redraw_count + 1 return true end -- cgit From e164f4c2715c97b48607bb6339eac3aff7106c47 Mon Sep 17 00:00:00 2001 From: Yi Ming Date: Mon, 18 Dec 2023 08:11:47 +0800 Subject: docs(diagnostic): add return value of `vim.diagnostic.config()` (#26615) --- runtime/lua/vim/diagnostic.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 2171ae14e6..e4f694b8a2 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -617,6 +617,8 @@ end --- ---@param namespace integer|nil Update the options for the given namespace. When omitted, update the --- global diagnostic options. +--- +---@return table|nil table of current diagnostic config if `opts` is omitted. function M.config(opts, namespace) vim.validate({ opts = { opts, 't', true }, -- cgit From 3a4aa3fc58f87a295a075fe457bc78805eef7c4d Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Mon, 18 Dec 2023 11:04:44 -0600 Subject: refactor: soft-deprecate diagnostic signs configured with :sign-define (#26618) Diagnostic signs should now be configured with vim.diagnostic.config(), but "legacy" sign definitions should go through the standard deprecation process to minimize the impact from breaking changes. --- runtime/lua/vim/diagnostic.lua | 49 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index e4f694b8a2..6d2c212dfc 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -588,7 +588,7 @@ end --- return diagnostic.message --- end --- ---- - signs: (default true) Use signs for diagnostics. Options: +--- - signs: (default true) Use signs for diagnostics |diagnostic-signs|. Options: --- * severity: Only show signs for diagnostics matching the given --- severity |diagnostic-severity| --- * priority: (number, default 10) Base priority to use for signs. When @@ -883,7 +883,52 @@ M.handlers.signs = { api.nvim_create_namespace(string.format('%s/diagnostic/signs', ns.name)) end - local text = {} + --- Handle legacy diagnostic sign definitions + --- These were deprecated in 0.10 and will be removed in 0.12 + if opts.signs and not opts.signs.text and not opts.signs.numhl and not opts.signs.texthl then + for _, v in ipairs({ 'Error', 'Warn', 'Info', 'Hint' }) do + local name = string.format('DiagnosticSign%s', v) + local sign = vim.fn.sign_getdefined(name)[1] + if sign then + local severity = M.severity[v:upper()] + if vim.fn.has('nvim-0.11') == 1 then + vim.deprecate( + 'Defining diagnostic signs with :sign-define or sign_define()', + 'vim.diagnostic.config()', + '0.12', + nil, + false + ) + end + + if not opts.signs.text then + opts.signs.text = {} + end + + if not opts.signs.numhl then + opts.signs.numhl = {} + end + + if not opts.signs.linehl then + opts.signs.linehl = {} + end + + if opts.signs.text[severity] == nil then + opts.signs.text[severity] = sign.text or '' + end + + if opts.signs.numhl[severity] == nil then + opts.signs.numhl[severity] = sign.numhl + end + + if opts.signs.linehl[severity] == nil then + opts.signs.linehl[severity] = sign.linehl + end + end + end + end + + local text = {} ---@type table for k in pairs(M.severity) do if opts.signs.text and opts.signs.text[k] then text[k] = opts.signs.text[k] -- cgit From 428edcde7068ab44040e19b43343741e5ca59770 Mon Sep 17 00:00:00 2001 From: Amanda Graven Date: Tue, 28 Nov 2023 21:05:33 +0100 Subject: feat(api): add forward and back mouse buttons --- runtime/lua/vim/_meta/api.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index c8afbd58dd..c8c3e1c3af 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1375,7 +1375,7 @@ function vim.api.nvim_input(keys) end --- processed soon by the event loop. --- --- @param button string Mouse button: one of "left", "right", "middle", "wheel", ---- "move". +--- "move", "x1", "x2". --- @param action string For ordinary buttons, one of "press", "drag", "release". --- For the wheel, one of "up", "down", "left", "right". --- Ignored for "move". -- cgit From 693aea0e9e1032aee85d56c1a3f33e0811dbdc18 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 19 Dec 2023 06:29:13 +0100 Subject: docs: small fixes (#26448) Co-authored-by: Gregory Anders <8965202+gpanders@users.noreply.github.com> Co-authored-by: Jordan Mandel --- runtime/lua/vim/_meta/options.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index e63c5bb972..6b7cfa79b3 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -1049,11 +1049,11 @@ vim.bo.cfu = vim.bo.completefunc --- completion in the preview window. Only works in --- combination with "menu" or "menuone". --- ---- noinsert Do not insert any text for a match until the user selects +--- noinsert Do not insert any text for a match until the user selects --- a match from the menu. Only works in combination with --- "menu" or "menuone". No effect if "longest" is present. --- ---- noselect Do not select a match in the menu, force the user to +--- noselect Do not select a match in the menu, force the user to --- select one from the menu. Only works in combination with --- "menu" or "menuone". --- -- cgit From 90a12d4a164315628c01043108b6aaa8f3afb102 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Mon, 18 Dec 2023 21:02:32 +0900 Subject: fix(treesitter): prepare highlight states for [s, ]s --- runtime/lua/vim/treesitter/highlighter.lua | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 17543bc787..b2cc334bdc 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -163,6 +163,8 @@ end ---@param erow integer exclusive ---@private function TSHighlighter:prepare_highlight_states(srow, erow) + self._highlight_states = {} + self.tree:for_each_tree(function(tstree, tree) if not tstree then return @@ -202,11 +204,6 @@ function TSHighlighter:for_each_highlight_state(fn) end end ----@private -function TSHighlighter:reset_highlight_state() - self._highlight_states = {} -end - ---@package ---@param start_row integer ---@param new_end integer @@ -327,7 +324,7 @@ function TSHighlighter._on_spell_nav(_, _, buf, srow, _, erow, _) return end - self:reset_highlight_state() + self:prepare_highlight_states(srow, erow) for row = srow, erow do on_line_impl(self, buf, row, true) @@ -345,7 +342,6 @@ function TSHighlighter._on_win(_, _win, buf, topline, botline) return false end self.tree:parse({ topline, botline + 1 }) - self:reset_highlight_state() self:prepare_highlight_states(topline, botline + 1) self.redraw_count = self.redraw_count + 1 return true -- cgit From 2ed784f3859bb0e70ae4ba79a99866cddd54219b Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 19 Dec 2023 23:21:07 +0100 Subject: vim-patch:9.0.2179: no filetype detection for execline scripts Problem: no filetype detection for execline scripts Solution: Add filetype detection for execline as a prior to adding syntax support for execline (see https://github.com/djpohly/vim-execline/issues/2), i went ahead and made the filetype detection for execline scripts. closes: vim/vim#13689 Signed-Off-By: Mazunki Hoksaas https://github.com/vim/vim/commit/63210c214afa6589b6132bd060908a8711f4567f Co-authored-by: Mazunki Hoksaas --- runtime/lua/vim/filetype.lua | 5 +++++ runtime/lua/vim/filetype/detect.lua | 1 + 2 files changed, 6 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index e64923ab54..9141b1e4c6 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1656,6 +1656,11 @@ local pattern = { ['.*/dtrace/.*%.d'] = 'dtrace', ['.*esmtprc'] = 'esmtprc', ['.*Eterm/.*%.cfg'] = 'eterm', + ['.*s6.*/up'] = 'execline', + ['.*s6.*/down'] = 'execline', + ['.*s6.*/run'] = 'execline', + ['.*s6.*/finish'] = 'execline', + ['s6%-.*'] = 'execline', ['[a-zA-Z0-9].*Dict'] = detect.foam, ['[a-zA-Z0-9].*Dict%..*'] = detect.foam, ['[a-zA-Z].*Properties'] = detect.foam, diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua index 9d0f1bd3ab..a1c5ac73b4 100644 --- a/runtime/lua/vim/filetype/detect.lua +++ b/runtime/lua/vim/filetype/detect.lua @@ -1661,6 +1661,7 @@ local patterns_hashbang = { ['^\\%(rexx\\|regina\\)\\>'] = { 'rexx', { vim_regex = true } }, ['^janet\\>'] = { 'janet', { vim_regex = true } }, ['^dart\\>'] = { 'dart', { vim_regex = true } }, + ['^execlineb\\>'] = { 'execline', { vim_regex = true } }, } ---@private -- cgit From 2498747addaf96dacba2000e6fbdf05572d129a3 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 20 Dec 2023 10:48:39 +0000 Subject: refactor(treesitter): cleanup highlighter - Remove some unused fields - Prefix classes with `vim.` - Move around some functions so the query stuff is at the top. - Improve type hints - Rework how hl_cache is implemented --- runtime/lua/vim/treesitter/highlighter.lua | 120 +++++++++++++++-------------- 1 file changed, 63 insertions(+), 57 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index b2cc334bdc..5ffdd79326 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -2,52 +2,25 @@ local api = vim.api local query = vim.treesitter.query local Range = require('vim.treesitter._range') ----@alias TSHlIter fun(end_line: integer|nil): integer, TSNode, TSMetadata - ----@class TSHighlightState ----@field tstree TSTree ----@field next_row integer ----@field iter TSHlIter|nil ----@field highlighter_query TSHighlighterQuery - ----@class TSHighlighter ----@field active table ----@field bufnr integer ----@field orig_spelloptions string ----@field _highlight_states TSHighlightState[] ----@field _queries table ----@field tree LanguageTree ----@field redraw_count integer -local TSHighlighter = rawget(vim.treesitter, 'TSHighlighter') or {} -TSHighlighter.__index = TSHighlighter +local ns = api.nvim_create_namespace('treesitter/highlighter') ---- @nodoc -TSHighlighter.active = TSHighlighter.active or {} +---@alias vim.TSHlIter fun(end_line: integer|nil): integer, TSNode, TSMetadata ----@class TSHighlighterQuery ----@field _query Query|nil ----@field hl_cache table +---@class vim.TSHighlighterQuery +---@field private _query Query? +---@field private lang string +---@field private hl_cache table local TSHighlighterQuery = {} TSHighlighterQuery.__index = TSHighlighterQuery -local ns = api.nvim_create_namespace('treesitter/highlighter') - ---@private +---@param lang string +---@param query_string string? +---@return vim.TSHighlighterQuery function TSHighlighterQuery.new(lang, query_string) - local self = setmetatable({}, { __index = TSHighlighterQuery }) - - self.hl_cache = setmetatable({}, { - __index = function(table, capture) - local name = self._query.captures[capture] - local id = 0 - if not vim.startswith(name, '_') then - id = api.nvim_get_hl_id_by_name('@' .. name .. '.' .. lang) - end - - rawset(table, capture, id) - return id - end, - }) + local self = setmetatable({}, TSHighlighterQuery) + self.lang = lang + self.hl_cache = {} if query_string then self._query = query.parse(lang, query_string) @@ -58,11 +31,49 @@ function TSHighlighterQuery.new(lang, query_string) return self end +---@package +---@param capture integer +---@return integer? +function TSHighlighterQuery:get_hl_from_capture(capture) + if not self.hl_cache[capture] then + local name = self._query.captures[capture] + local id = 0 + if not vim.startswith(name, '_') then + id = api.nvim_get_hl_id_by_name('@' .. name .. '.' .. self.lang) + end + self.hl_cache[capture] = id + end + + return self.hl_cache[capture] +end + ---@package function TSHighlighterQuery:query() return self._query end +---@class vim.TSHighlightState +---@field tstree TSTree +---@field next_row integer +---@field iter vim.TSHlIter? +---@field highlighter_query vim.TSHighlighterQuery + +---@class vim.TSHighlighter +---@field active table +---@field bufnr integer +---@field orig_spelloptions string +--- A map of highlight states. +--- This state is kept during rendering across each line update. +---@field _highlight_states vim.TSHighlightState[] +---@field _queries table +---@field tree LanguageTree +---@field redraw_count integer +local TSHighlighter = { + active = {}, +} + +TSHighlighter.__index = TSHighlighter + ---@package --- --- Creates a highlighter for `tree`. @@ -70,7 +81,7 @@ end ---@param tree LanguageTree parser object to use for highlighting ---@param opts (table|nil) Configuration of the highlighter: --- - queries table overwrite queries used by the highlighter ----@return TSHighlighter Created highlighter object +---@return vim.TSHighlighter Created highlighter object function TSHighlighter.new(tree, opts) local self = setmetatable({}, TSHighlighter) @@ -100,15 +111,12 @@ function TSHighlighter.new(tree, opts) end, }, true) - self.bufnr = tree:source() --[[@as integer]] - self.edit_count = 0 + local source = tree:source() + assert(type(source) == 'number') + + self.bufnr = source self.redraw_count = 0 - self.line_count = {} - -- A map of highlight states. - -- This state is kept during rendering across each line update. self._highlight_states = {} - - ---@type table self._queries = {} -- Queries for a specific language can be overridden by a custom @@ -146,11 +154,9 @@ end --- @nodoc --- Removes all internal references to the highlighter function TSHighlighter:destroy() - if TSHighlighter.active[self.bufnr] then - TSHighlighter.active[self.bufnr] = nil - end + TSHighlighter.active[self.bufnr] = nil - if vim.api.nvim_buf_is_loaded(self.bufnr) then + if api.nvim_buf_is_loaded(self.bufnr) then vim.bo[self.bufnr].spelloptions = self.orig_spelloptions vim.b[self.bufnr].ts_highlight = nil if vim.g.syntax_on == 1 then @@ -173,7 +179,7 @@ function TSHighlighter:prepare_highlight_states(srow, erow) local root_node = tstree:root() local root_start_row, _, root_end_row, _ = root_node:range() - -- Only worry about trees within the visible range + -- Only consider trees within the visible range if root_start_row > erow or root_end_row < srow then return end @@ -196,7 +202,7 @@ function TSHighlighter:prepare_highlight_states(srow, erow) end) end ----@param fn fun(state: TSHighlightState) +---@param fn fun(state: vim.TSHighlightState) ---@package function TSHighlighter:for_each_highlight_state(fn) for _, state in ipairs(self._highlight_states) do @@ -228,7 +234,7 @@ end -- ---@package ---@param lang string Language used by the highlighter. ----@return TSHighlighterQuery +---@return vim.TSHighlighterQuery function TSHighlighter:get_query(lang) if not self._queries[lang] then self._queries[lang] = TSHighlighterQuery.new(lang) @@ -237,7 +243,7 @@ function TSHighlighter:get_query(lang) return self._queries[lang] end ----@param self TSHighlighter +---@param self vim.TSHighlighter ---@param buf integer ---@param line integer ---@param is_spell_nav boolean @@ -246,7 +252,7 @@ local function on_line_impl(self, buf, line, is_spell_nav) local root_node = state.tstree:root() local root_start_row, _, root_end_row, _ = root_node:range() - -- Only worry about trees within the line range + -- Only consider trees that contain this line if root_start_row > line or root_end_row < line then return end @@ -266,7 +272,7 @@ local function on_line_impl(self, buf, line, is_spell_nav) local start_row, start_col, end_row, end_col = Range.unpack4(range) if capture then - local hl = state.highlighter_query.hl_cache[capture] + local hl = state.highlighter_query:get_hl_from_capture(capture) local capture_name = state.highlighter_query:query().captures[capture] local spell = nil ---@type boolean? -- cgit From cc6a257c8cad8051b6f7e9287249293ab0a929d9 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Mon, 18 Dec 2023 16:49:44 +0100 Subject: docs: apply current colorscheme to default highlight groups Problem: Not all default highlight groups show their actual colors. Solution: Refactor `vimhelp.lua` and apply it to all relevant lists (UI groups, syntax groups, treesitter groups, LSP groups, diagnostic groups). --- runtime/lua/vim/vimhelp.lua | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/vimhelp.lua b/runtime/lua/vim/vimhelp.lua index a4d6a50b12..4af6866d48 100644 --- a/runtime/lua/vim/vimhelp.lua +++ b/runtime/lua/vim/vimhelp.lua @@ -2,26 +2,28 @@ local M = {} --- Called when editing the doc/syntax.txt file -function M.highlight_groups() - local save_cursor = vim.fn.getcurpos() - - local start_lnum = vim.fn.search([[\*highlight-groups\*]], 'c') - if start_lnum == 0 then - return - end - local end_lnum = vim.fn.search('^======') - if end_lnum == 0 then - return - end - +--- Apply current colorscheme to lists of default highlight groups +--- +--- Note: {patterns} is assumed to be sorted by occurrence in the file. +--- @param patterns {start:string,stop:string,match:string}[] +function M.highlight_groups(patterns) local ns = vim.api.nvim_create_namespace('vimhelp') vim.api.nvim_buf_clear_namespace(0, ns, 0, -1) - for lnum = start_lnum, end_lnum do - local word = vim.api.nvim_buf_get_lines(0, lnum - 1, lnum, true)[1]:match('^(%w+)\t') - if vim.fn.hlexists(word) ~= 0 then - vim.api.nvim_buf_set_extmark(0, ns, lnum - 1, 0, { end_col = #word, hl_group = word }) + local save_cursor = vim.fn.getcurpos() + + for _, pat in pairs(patterns) do + local start_lnum = vim.fn.search(pat.start, 'c') + local end_lnum = vim.fn.search(pat.stop) + if start_lnum == 0 or end_lnum == 0 then + break + end + + for lnum = start_lnum, end_lnum do + local word = vim.api.nvim_buf_get_lines(0, lnum - 1, lnum, true)[1]:match(pat.match) + if vim.fn.hlexists(word) ~= 0 then + vim.api.nvim_buf_set_extmark(0, ns, lnum - 1, 0, { end_col = #word, hl_group = word }) + end end end -- cgit From 104565909798eff57d0bd46c56d149055b8a739b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 21 Dec 2023 11:47:04 +0800 Subject: fix(osc52): use nvim_chan_send() to stderr for copying (#26690) The data to be written can be very long, so use nvim_chan_send() instead of io.stdout:write() as the latter doesn't handle EAGAIN. A difference of these two approaches is that nvim_chan_send() writes to stderr, not stdout, so it won't work if client stderr is redirected. --- runtime/lua/vim/ui/clipboard/osc52.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/ui/clipboard/osc52.lua b/runtime/lua/vim/ui/clipboard/osc52.lua index 6483f0387d..50afbe63a5 100644 --- a/runtime/lua/vim/ui/clipboard/osc52.lua +++ b/runtime/lua/vim/ui/clipboard/osc52.lua @@ -13,7 +13,9 @@ function M.copy(reg) local clipboard = reg == '+' and 'c' or 'p' return function(lines) local s = table.concat(lines, '\n') - io.stdout:write(osc52(clipboard, vim.base64.encode(s))) + -- The data to be written here can be quite long. + -- Use nvim_chan_send() as io.stdout:write() doesn't handle EAGAIN. #26688 + vim.api.nvim_chan_send(2, osc52(clipboard, vim.base64.encode(s))) end end -- cgit From e8d3c4cccb9d362952a09216a5a114ee6d024c14 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 20 Dec 2023 16:34:17 +0000 Subject: feat: generate types and docs for v variables --- runtime/lua/vim/_meta/vvars.lua | 765 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 757 insertions(+), 8 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vvars.lua b/runtime/lua/vim/_meta/vvars.lua index 059ef04203..e3b89aeff7 100644 --- a/runtime/lua/vim/_meta/vvars.lua +++ b/runtime/lua/vim/_meta/vvars.lua @@ -1,23 +1,772 @@ --- @meta _ - --- TODO(lewis6991): generate this and `:help vim-variable` +-- THIS FILE IS GENERATED +-- DO NOT EDIT +error('Cannot require a meta file') --- @class vim.v +vim.v = ... + +--- The command line arguments Vim was invoked with. This is a +--- list of strings. The first item is the Vim command. +--- See `v:progpath` for the command with full path. +--- @type string[] +vim.v.argv = ... + +--- Argument for evaluating 'formatexpr' and used for the typed +--- character when using in an abbreviation `:map-`. +--- It is also used by the `InsertCharPre` and `InsertEnter` events. +--- @type any +vim.v.char = ... + +--- The name of the character encoding of a file to be converted. +--- Only valid while evaluating the 'charconvert' option. +--- @type string +vim.v.charconvert_from = ... + +--- The name of the character encoding of a file after conversion. +--- Only valid while evaluating the 'charconvert' option. +--- @type string +vim.v.charconvert_to = ... + +--- The extra arguments ("++p", "++enc=", "++ff=") given to a file +--- read/write command. This is set before an autocommand event +--- for a file read/write command is triggered. There is a +--- leading space to make it possible to append this variable +--- directly after the read/write command. Note: "+cmd" isn't +--- included here, because it will be executed anyway. +--- @type string[] +vim.v.cmdarg = ... + +--- Set like v:cmdarg for a file read/write command. When a "!" +--- was used the value is 1, otherwise it is 0. Note that this +--- can only be used in autocommands. For user commands `` +--- can be used. +--- @type any +vim.v.cmdbang = ... + +--- The current locale setting for collation order of the runtime +--- environment. This allows Vim scripts to be aware of the +--- current locale encoding. Technical: it's the value of +--- LC_COLLATE. When not using a locale the value is "C". +--- This variable can not be set directly, use the `:language` +--- command. +--- See `multi-lang`. +--- @type string +vim.v.collate = ... + +--- Dictionary containing the most recent `complete-items` after +--- `CompleteDone`. Empty if the completion failed, or after +--- leaving and re-entering insert mode. +--- Note: Plugins can modify the value to emulate the builtin +--- `CompleteDone` event behavior. +--- @type any +vim.v.completed_item = ... + --- The count given for the last Normal mode command. Can be used --- to get the count before a mapping. Read-only. Example: +--- --- ```vim ---- :map _x :echo "the count is " .. v:count +--- :map _x :echo "the count is " .. v:count --- ``` +--- --- Note: The is required to remove the line range that you --- get when typing ':' after a count. --- When there are two counts, as in "3d2w", they are multiplied, --- just like what happens in the command, "d6w" for the example. --- Also used for evaluating the 'formatexpr' option. ---- @field count integer +--- @type integer +vim.v.count = ... + +--- Just like "v:count", but defaults to one when no count is +--- used. +--- @type integer +vim.v.count1 = ... + +--- The current locale setting for characters of the runtime +--- environment. This allows Vim scripts to be aware of the +--- current locale encoding. Technical: it's the value of +--- LC_CTYPE. When not using a locale the value is "C". +--- This variable can not be set directly, use the `:language` +--- command. +--- See `multi-lang`. +--- @type any +vim.v.ctype = ... + +--- Normally zero. When a deadly signal is caught it's set to +--- one. When multiple signals are caught the number increases. +--- Can be used in an autocommand to check if Vim didn't +--- terminate normally. +--- Example: +--- +--- ```vim +--- :au VimLeave * if v:dying | echo "\nAAAAaaaarrrggghhhh!!!\n" | endif +--- ``` --- ---- Line number for the 'foldexpr' |fold-expr|, 'formatexpr', +--- Note: if another deadly signal is caught when v:dying is one, +--- VimLeave autocommands will not be executed. +--- @type integer +vim.v.dying = ... + +--- Number of screen cells that can be used for an `:echo` message +--- in the last screen line before causing the `hit-enter-prompt`. +--- Depends on 'showcmd', 'ruler' and 'columns'. You need to +--- check 'cmdheight' for whether there are full-width lines +--- available above the last line. +--- @type integer +vim.v.echospace = ... + +--- Last given error message. +--- Modifiable (can be set). +--- Example: +--- +--- ```vim +--- let v:errmsg = "" +--- silent! next +--- if v:errmsg != "" +--- " ... handle error +--- ``` +--- @type string +vim.v.errmsg = ... + +--- Errors found by assert functions, such as `assert_true()`. +--- This is a list of strings. +--- The assert functions append an item when an assert fails. +--- The return value indicates this: a one is returned if an item +--- was added to v:errors, otherwise zero is returned. +--- To remove old results make it empty: +--- +--- ```vim +--- let v:errors = [] +--- ``` +--- +--- If v:errors is set to anything but a list it is made an empty +--- list by the assert function. +--- @type any +vim.v.errors = ... + +--- Dictionary of event data for the current `autocommand`. Valid +--- only during the event lifetime; storing or passing v:event is +--- invalid! Copy it instead: +--- +--- ```vim +--- au TextYankPost * let g:foo = deepcopy(v:event) +--- ``` +--- +--- Keys vary by event; see the documentation for the specific +--- event, e.g. `DirChanged` or `TextYankPost`. +--- KEY DESCRIPTION ~ +--- abort Whether the event triggered during +--- an aborting condition (e.g. `c_Esc` or +--- `c_CTRL-C` for `CmdlineLeave`). +--- chan `channel-id` +--- cmdlevel Level of cmdline. +--- cmdtype Type of cmdline, `cmdline-char`. +--- cwd Current working directory. +--- inclusive Motion is `inclusive`, else exclusive. +--- scope Event-specific scope name. +--- operator Current `operator`. Also set for Ex +--- commands (unlike `v:operator`). For +--- example if `TextYankPost` is triggered +--- by the `:yank` Ex command then +--- `v:event.operator` is "y". +--- regcontents Text stored in the register as a +--- `readfile()`-style list of lines. +--- regname Requested register (e.g "x" for "xyy) +--- or the empty string for an unnamed +--- operation. +--- regtype Type of register as returned by +--- `getregtype()`. +--- visual Selection is visual (as opposed to, +--- e.g., via motion). +--- completed_item Current selected complete item on +--- `CompleteChanged`, Is `{}` when no complete +--- item selected. +--- height Height of popup menu on `CompleteChanged` +--- width Width of popup menu on `CompleteChanged` +--- row Row count of popup menu on `CompleteChanged`, +--- relative to screen. +--- col Col count of popup menu on `CompleteChanged`, +--- relative to screen. +--- size Total number of completion items on +--- `CompleteChanged`. +--- scrollbar Is `v:true` if popup menu have scrollbar, or +--- `v:false` if not. +--- changed_window Is `v:true` if the event fired while +--- changing window (or tab) on `DirChanged`. +--- status Job status or exit code, -1 means "unknown". `TermClose` +--- @type any +vim.v.event = ... + +--- The value of the exception most recently caught and not +--- finished. See also `v:throwpoint` and `throw-variables`. +--- Example: +--- +--- ```vim +--- try +--- throw "oops" +--- catch /.*/ +--- echo "caught " .. v:exception +--- endtry +--- ``` +--- +--- Output: "caught oops". +--- @type any +vim.v.exception = ... + +--- Exit code, or `v:null` before invoking the `VimLeavePre` +--- and `VimLeave` autocmds. See `:q`, `:x` and `:cquit`. +--- Example: +--- +--- ```vim +--- :au VimLeave * echo "Exit value is " .. v:exiting +--- ``` +--- @type any +vim.v.exiting = ... + +--- Special value used to put "false" in JSON and msgpack. See +--- `json_encode()`. This value is converted to "v:false" when used +--- as a String (e.g. in `expr5` with string concatenation +--- operator) and to zero when used as a Number (e.g. in `expr5` +--- or `expr7` when used with numeric operators). Read-only. +--- @type any +vim.v['false'] = ... + +--- What should happen after a `FileChangedShell` event was +--- triggered. Can be used in an autocommand to tell Vim what to +--- do with the affected buffer: +--- reload Reload the buffer (does not work if +--- the file was deleted). +--- edit Reload the buffer and detect the +--- values for options such as +--- 'fileformat', 'fileencoding', 'binary' +--- (does not work if the file was +--- deleted). +--- ask Ask the user what to do, as if there +--- was no autocommand. Except that when +--- only the timestamp changed nothing +--- will happen. +--- Nothing, the autocommand should do +--- everything that needs to be done. +--- The default is empty. If another (invalid) value is used then +--- Vim behaves like it is empty, there is no warning message. +--- @type string +vim.v.fcs_choice = ... + +--- The reason why the `FileChangedShell` event was triggered. +--- Can be used in an autocommand to decide what to do and/or what +--- to set v:fcs_choice to. Possible values: +--- deleted file no longer exists +--- conflict file contents, mode or timestamp was +--- changed and buffer is modified +--- changed file contents has changed +--- mode mode of file changed +--- time only file timestamp changed +--- @type string +vim.v.fcs_reason = ... + +--- When evaluating 'includeexpr': the file name that was +--- detected. Empty otherwise. +--- @type string +vim.v.fname = ... + +--- The name of the diff (patch) file. Only valid while +--- evaluating 'patchexpr'. +--- @type string +vim.v.fname_diff = ... + +--- The name of the input file. Valid while evaluating: +--- option used for ~ +--- 'charconvert' file to be converted +--- 'diffexpr' original file +--- 'patchexpr' original file +--- And set to the swap file name for `SwapExists`. +--- @type string +vim.v.fname_in = ... + +--- The name of the new version of the file. Only valid while +--- evaluating 'diffexpr'. +--- @type string +vim.v.fname_new = ... + +--- The name of the output file. Only valid while +--- evaluating: +--- option used for ~ +--- 'charconvert' resulting converted file [1] +--- 'diffexpr' output of diff +--- 'patchexpr' resulting patched file +--- [1] When doing conversion for a write command (e.g., ":w +--- file") it will be equal to v:fname_in. When doing conversion +--- for a read command (e.g., ":e file") it will be a temporary +--- file and different from v:fname_in. +--- @type string +vim.v.fname_out = ... + +--- Used for 'foldtext': dashes representing foldlevel of a closed +--- fold. +--- Read-only in the `sandbox`. `fold-foldtext` +--- @type string +vim.v.folddashes = ... + +--- Used for 'foldtext': last line of closed fold. +--- Read-only in the `sandbox`. `fold-foldtext` +--- @type integer +vim.v.foldend = ... + +--- Used for 'foldtext': foldlevel of closed fold. +--- Read-only in the `sandbox`. `fold-foldtext` +--- @type integer +vim.v.foldlevel = ... + +--- Used for 'foldtext': first line of closed fold. +--- Read-only in the `sandbox`. `fold-foldtext` +--- @type integer +vim.v.foldstart = ... + +--- Variable that indicates whether search highlighting is on. +--- Setting it makes sense only if 'hlsearch' is enabled. Setting +--- this variable to zero acts like the `:nohlsearch` command, +--- setting it to one acts like +--- +--- ```vim +--- let &hlsearch = &hlsearch +--- ``` +--- +--- Note that the value is restored when returning from a +--- function. `function-search-undo`. +--- @type integer +vim.v.hlsearch = ... + +--- Used for the `InsertEnter` and `InsertChange` autocommand +--- events. Values: +--- i Insert mode +--- r Replace mode +--- v Virtual Replace mode +--- @type string +vim.v.insertmode = ... + +--- Key of the current item of a `Dictionary`. Only valid while +--- evaluating the expression used with `map()` and `filter()`. +--- Read-only. +--- @type string +vim.v.key = ... + +--- The current locale setting for messages of the runtime +--- environment. This allows Vim scripts to be aware of the +--- current language. Technical: it's the value of LC_MESSAGES. +--- The value is system dependent. +--- This variable can not be set directly, use the `:language` +--- command. +--- It can be different from `v:ctype` when messages are desired +--- in a different language than what is used for character +--- encoding. See `multi-lang`. +--- @type string +vim.v.lang = ... + +--- The current locale setting for time messages of the runtime +--- environment. This allows Vim scripts to be aware of the +--- current language. Technical: it's the value of LC_TIME. +--- This variable can not be set directly, use the `:language` +--- command. See `multi-lang`. +--- @type string +vim.v.lc_time = ... + +--- Line number for the 'foldexpr' `fold-expr`, 'formatexpr', --- 'indentexpr' and 'statuscolumn' expressions, tab page number --- for 'guitablabel' and 'guitabtooltip'. Only valid while one of ---- these expressions is being evaluated. Read-only when in the |sandbox|. ---- @field lnum integer -vim.v = ... +--- these expressions is being evaluated. Read-only when in the +--- `sandbox`. +--- @type integer +vim.v.lnum = ... + +--- Prefix for calling Lua functions from expressions. +--- See `v:lua-call` for more information. +--- @type any +vim.v.lua = ... + +--- Maximum line length. Depending on where it is used it can be +--- screen columns, characters or bytes. The value currently is +--- 2147483647 on all systems. +--- @type integer +vim.v.maxcol = ... + +--- Column number for a mouse click obtained with `getchar()`. +--- This is the screen column number, like with `virtcol()`. The +--- value is zero when there was no mouse button click. +--- @type integer +vim.v.mouse_col = ... + +--- Line number for a mouse click obtained with `getchar()`. +--- This is the text line number, not the screen line number. The +--- value is zero when there was no mouse button click. +--- @type integer +vim.v.mouse_lnum = ... + +--- Window number for a mouse click obtained with `getchar()`. +--- First window has number 1, like with `winnr()`. The value is +--- zero when there was no mouse button click. +--- @type integer +vim.v.mouse_win = ... + +--- `window-ID` for a mouse click obtained with `getchar()`. +--- The value is zero when there was no mouse button click. +--- @type integer +vim.v.mouse_winid = ... + +--- Dictionary containing msgpack types used by `msgpackparse()` +--- and `msgpackdump()`. All types inside dictionary are fixed +--- (not editable) empty lists. To check whether some list is one +--- of msgpack types, use `is` operator. +--- @type any +vim.v.msgpack_types = ... + +--- Special value used to put "null" in JSON and NIL in msgpack. +--- See `json_encode()`. This value is converted to "v:null" when +--- used as a String (e.g. in `expr5` with string concatenation +--- operator) and to zero when used as a Number (e.g. in `expr5` +--- or `expr7` when used with numeric operators). Read-only. +--- In some places `v:null` can be used for a List, Dict, etc. +--- that is not set. That is slightly different than an empty +--- List, Dict, etc. +--- @type any +vim.v.null = ... + +--- Maximum value of a number. +--- @type integer +vim.v.numbermax = ... + +--- Minimum value of a number (negative). +--- @type integer +vim.v.numbermin = ... + +--- Number of bits in a Number. This is normally 64, but on some +--- systems it may be 32. +--- @type integer +vim.v.numbersize = ... + +--- List of file names that is loaded from the `shada` file on +--- startup. These are the files that Vim remembers marks for. +--- The length of the List is limited by the ' argument of the +--- 'shada' option (default is 100). +--- When the `shada` file is not used the List is empty. +--- Also see `:oldfiles` and `c_#<`. +--- The List can be modified, but this has no effect on what is +--- stored in the `shada` file later. If you use values other +--- than String this will cause trouble. +--- @type string[] +vim.v.oldfiles = ... + +--- The last operator given in Normal mode. This is a single +--- character except for commands starting with or , +--- in which case it is two characters. Best used alongside +--- `v:prevcount` and `v:register`. Useful if you want to cancel +--- Operator-pending mode and then use the operator, e.g.: +--- +--- ```vim +--- :omap O :call MyMotion(v:operator) +--- ``` +--- +--- The value remains set until another operator is entered, thus +--- don't expect it to be empty. +--- v:operator is not set for `:delete`, `:yank` or other Ex +--- commands. +--- Read-only. +--- @type string +vim.v.operator = ... + +--- Command used to set the option. Valid while executing an +--- `OptionSet` autocommand. +--- value option was set via ~ +--- "setlocal" `:setlocal` or `:let l:xxx` +--- "setglobal" `:setglobal` or `:let g:xxx` +--- "set" `:set` or `:let` +--- "modeline" `modeline` +--- @type string +vim.v.option_command = ... + +--- New value of the option. Valid while executing an `OptionSet` +--- autocommand. +--- @type any +vim.v.option_new = ... + +--- Old value of the option. Valid while executing an `OptionSet` +--- autocommand. Depending on the command used for setting and the +--- kind of option this is either the local old value or the +--- global old value. +--- @type any +vim.v.option_old = ... + +--- Old global value of the option. Valid while executing an +--- `OptionSet` autocommand. +--- @type any +vim.v.option_oldglobal = ... + +--- Old local value of the option. Valid while executing an +--- `OptionSet` autocommand. +--- @type any +vim.v.option_oldlocal = ... + +--- Scope of the set command. Valid while executing an +--- `OptionSet` autocommand. Can be either "global" or "local" +--- @type string +vim.v.option_type = ... + +--- The count given for the last but one Normal mode command. +--- This is the v:count value of the previous command. Useful if +--- you want to cancel Visual or Operator-pending mode and then +--- use the count, e.g.: +--- +--- ```vim +--- :vmap % :call MyFilter(v:prevcount) +--- ``` +--- +--- Read-only. +--- @type integer +vim.v.prevcount = ... + +--- Normally zero. Set to one after using ":profile start". +--- See `profiling`. +--- @type integer +vim.v.profiling = ... + +--- The name by which Nvim was invoked (with path removed). +--- Read-only. +--- @type string +vim.v.progname = ... + +--- Absolute path to the current running Nvim. +--- Read-only. +--- @type string +vim.v.progpath = ... + +--- The name of the register in effect for the current normal mode +--- command (regardless of whether that command actually used a +--- register). Or for the currently executing normal mode mapping +--- (use this in custom commands that take a register). +--- If none is supplied it is the default register '"', unless +--- 'clipboard' contains "unnamed" or "unnamedplus", then it is +--- "*" or '+'. +--- Also see `getreg()` and `setreg()` +--- @type string +vim.v.register = ... + +--- Relative line number for the 'statuscolumn' expression. +--- Read-only. +--- @type integer +vim.v.relnum = ... + +--- String describing the script or function that caused the +--- screen to scroll up. It's only set when it is empty, thus the +--- first reason is remembered. It is set to "Unknown" for a +--- typed command. +--- This can be used to find out why your script causes the +--- hit-enter prompt. +--- @type any +vim.v.scrollstart = ... + +--- Search direction: 1 after a forward search, 0 after a +--- backward search. It is reset to forward when directly setting +--- the last search pattern, see `quote/`. +--- Note that the value is restored when returning from a +--- function. `function-search-undo`. +--- Read-write. +--- @type integer +vim.v.searchforward = ... + +--- Primary listen-address of Nvim, the first item returned by +--- `serverlist()`. Usually this is the named pipe created by Nvim +--- at `startup` or given by `--listen` (or the deprecated +--- `$NVIM_LISTEN_ADDRESS` env var). +--- +--- See also `serverstart()` `serverstop()`. +--- Read-only. +--- +--- *$NVIM* +--- $NVIM is set by `terminal` and `jobstart()`, and is thus +--- a hint that the current environment is a subprocess of Nvim. +--- Example: +--- +--- ```vim +--- if $NVIM +--- echo nvim_get_chan_info(v:parent) +--- endif +--- ``` +--- +--- Note the contents of $NVIM may change in the future. +--- @type string +vim.v.servername = ... + +--- Result of the last shell command. When non-zero, the last +--- shell command had an error. When zero, there was no problem. +--- This only works when the shell returns the error code to Vim. +--- The value -1 is often used when the command could not be +--- executed. Read-only. +--- Example: +--- +--- ```vim +--- !mv foo bar +--- if v:shell_error +--- echo 'could not rename "foo" to "bar"!' +--- endif +--- ``` +--- @type string +vim.v.shell_error = ... + +--- Last given status message. +--- Modifiable (can be set). +--- @type string +vim.v.statusmsg = ... + +--- `channel-id` corresponding to stderr. The value is always 2; +--- use this variable to make your code more descriptive. +--- Unlike stdin and stdout (see `stdioopen()`), stderr is always +--- open for writing. Example: +--- +--- ```vim +--- :call chansend(v:stderr, "error: toaster empty\n") +--- ``` +--- @type string +vim.v.stderr = ... + +--- `SwapExists` autocommands can set this to the selected choice +--- for handling an existing swapfile: +--- 'o' Open read-only +--- 'e' Edit anyway +--- 'r' Recover +--- 'd' Delete swapfile +--- 'q' Quit +--- 'a' Abort +--- The value should be a single-character string. An empty value +--- results in the user being asked, as would happen when there is +--- no SwapExists autocommand. The default is empty. +--- @type string +vim.v.swapchoice = ... + +--- Normal mode command to be executed after a file has been +--- opened. Can be used for a `SwapExists` autocommand to have +--- another Vim open the file and jump to the right place. For +--- example, when jumping to a tag the value is ":tag tagname\r". +--- For ":edit +cmd file" the value is ":cmd\r". +--- @type string +vim.v.swapcommand = ... + +--- Name of the swapfile found. +--- Only valid during `SwapExists` event. +--- Read-only. +--- @type string +vim.v.swapname = ... + +--- Value of `Blob` type. Read-only. See: `type()` +--- @type integer +vim.v.t_blob = ... + +--- Value of `Boolean` type. Read-only. See: `type()` +--- @type integer +vim.v.t_bool = ... + +--- Value of `Dictionary` type. Read-only. See: `type()` +--- @type integer +vim.v.t_dict = ... + +--- Value of `Float` type. Read-only. See: `type()` +--- @type integer +vim.v.t_float = ... + +--- Value of `Funcref` type. Read-only. See: `type()` +--- @type integer +vim.v.t_func = ... + +--- Value of `List` type. Read-only. See: `type()` +--- @type integer +vim.v.t_list = ... + +--- Value of `Number` type. Read-only. See: `type()` +--- @type integer +vim.v.t_number = ... + +--- Value of `String` type. Read-only. See: `type()` +--- @type integer +vim.v.t_string = ... + +--- The value of the most recent OSC or DCS escape sequence +--- received by Nvim from the terminal. This can be read in a +--- `TermResponse` event handler after querying the terminal using +--- another escape sequence. +--- @type any +vim.v.termresponse = ... + +--- Must be set before using `test_garbagecollect_now()`. +--- @type any +vim.v.testing = ... + +--- Full filename of the last loaded or saved session file. +--- Empty when no session file has been saved. See `:mksession`. +--- Modifiable (can be set). +--- @type any +vim.v.this_session = ... + +--- The point where the exception most recently caught and not +--- finished was thrown. Not set when commands are typed. See +--- also `v:exception` and `throw-variables`. +--- Example: +--- +--- ```vim +--- try +--- throw "oops" +--- catch /.*/ +--- echo "Exception from" v:throwpoint +--- endtry +--- ``` +--- +--- Output: "Exception from test.vim, line 2" +--- @type any +vim.v.throwpoint = ... + +--- Special value used to put "true" in JSON and msgpack. See +--- `json_encode()`. This value is converted to "v:true" when used +--- as a String (e.g. in `expr5` with string concatenation +--- operator) and to one when used as a Number (e.g. in `expr5` or +--- `expr7` when used with numeric operators). Read-only. +--- @type any +vim.v['true'] = ... + +--- Value of the current item of a `List` or `Dictionary`. Only +--- valid while evaluating the expression used with `map()` and +--- `filter()`. Read-only. +--- @type any +vim.v.val = ... + +--- Vim version number: major version times 100 plus minor +--- version. Vim 5.0 is 500, Vim 5.1 is 501. +--- Read-only. +--- Use `has()` to check the Nvim (not Vim) version: +--- +--- ```vim +--- :if has("nvim-0.2.1") +--- ``` +--- @type integer +vim.v.version = ... + +--- 0 during startup, 1 just before `VimEnter`. +--- Read-only. +--- @type integer +vim.v.vim_did_enter = ... + +--- Virtual line number for the 'statuscolumn' expression. +--- Negative when drawing the status column for virtual lines, zero +--- when drawing an actual buffer line, and positive when drawing +--- the wrapped part of a buffer line. +--- Read-only. +--- @type integer +vim.v.virtnum = ... + +--- Last given warning message. +--- Modifiable (can be set). +--- @type string +vim.v.warningmsg = ... + +--- Application-specific window "handle" which may be set by any +--- attached UI. Defaults to zero. +--- Note: For Nvim `windows` use `winnr()` or `win_getid()`, see +--- `window-ID`. +--- @type integer +vim.v.windowid = ... -- cgit From 6700127b30d55e6ddf70495e7b886464172d7ac6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 22 Dec 2023 10:33:34 +0800 Subject: vim-patch:9.0.2183: Maximum callback depth is not configurable (#26703) Problem: Maximum callback depth is not configurable. Solution: Revert patch 9.0.2103. Set 'maxfuncdepth' in test. fixes: vim/vim#13732 closes: vim/vim#13736 https://github.com/vim/vim/commit/fe583b1e5987fbfdb5f2141c133dbff9665ed301 --- runtime/lua/vim/_meta/options.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 6b7cfa79b3..38ab66c96d 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -4037,6 +4037,7 @@ vim.go.mat = vim.go.matchtime --- Increasing this limit above 200 also changes the maximum for Ex --- command recursion, see `E169`. --- See also `:function`. +--- Also used for maximum depth of callback functions. --- --- @type integer vim.o.maxfuncdepth = 100 -- cgit From 19aba5916a4064b503894185072fb1c47a41e023 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 22 Dec 2023 10:55:39 +0100 Subject: docs(options): add codeblock annotations to options.lua (#26696) Also consistently remove leading colons in examples Co-authored-by: zeertzjq --- runtime/lua/vim/_meta/options.lua | 652 ++++++++++++++++++++++---------------- 1 file changed, 385 insertions(+), 267 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 38ab66c96d..209c27cfd8 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -137,8 +137,9 @@ vim.bo.ai = vim.bo.autoindent --- `timestamp` --- If this option has a local value, use this command to switch back to --- using the global value: ---- ``` ---- :set autoread< +--- +--- ```vim +--- set autoread< --- ``` --- --- @@ -198,10 +199,11 @@ vim.go.awa = vim.go.autowriteall --- --- Normally this option would be set in the vimrc file. Possibly --- depending on the terminal name. Example: ---- ``` ---- :if $TERM ==# "xterm" ---- : set background=dark ---- :endif +--- +--- ```vim +--- if $TERM ==# "xterm" +--- set background=dark +--- endif --- ``` --- When this option is changed, the default settings for the highlight groups --- will change. To use other settings, place ":highlight" commands AFTER @@ -348,14 +350,16 @@ vim.go.bkc = vim.go.backupcopy --- - Environment variables are expanded `:set_env`. --- - Careful with '\' characters, type one before a space, type two to --- get one in the option (see `option-backslash`), for example: ---- ``` ---- :set bdir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces +--- +--- ```vim +--- set bdir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces --- ``` --- --- See also 'backup' and 'writebackup' options. --- If you want to hide your backup files on Unix, consider this value: ---- ``` ---- :set backupdir=./.backup,~/.backup,.,/tmp +--- +--- ```vim +--- set backupdir=./.backup,~/.backup,.,/tmp --- ``` --- You must create a ".backup" directory in each directory and in your --- home directory for this to work properly. @@ -381,8 +385,9 @@ vim.go.bdir = vim.go.backupdir --- If you like to keep a lot of backups, you could use a BufWritePre --- autocommand to change 'backupext' just before writing the file to --- include a timestamp. ---- ``` ---- :au BufWritePre * let &bex = '-' .. strftime("%Y%b%d%X") .. '~' +--- +--- ```vim +--- au BufWritePre * let &bex = '-' .. strftime("%Y%b%d%X") .. '~' --- ``` --- Use 'backupdir' to put the backup in a different directory. --- @@ -409,7 +414,7 @@ vim.go.bex = vim.go.backupext --- $HOME you must expand it explicitly, e.g.: --- --- ```vim ---- :let &backupskip = escape(expand('$HOME'), '\') .. '/tmp/*' +--- let &backupskip = escape(expand('$HOME'), '\') .. '/tmp/*' --- ``` --- Note that the default also makes sure that "crontab -e" works (when a --- backup would be made by renaming the original file crontab won't see @@ -710,8 +715,9 @@ vim.go.cdh = vim.go.cdhome --- If the default value taken from $CDPATH is not what you want, include --- a modified version of the following command in your vimrc file to --- override it: ---- ``` ---- :let &cdpath = ',' .. substitute(substitute($CDPATH, '[, ]', '\\\0', 'g'), ':', ',', 'g') +--- +--- ```vim +--- let &cdpath = ',' .. substitute(substitute($CDPATH, '[, ]', '\\\0', 'g'), ':', ',', 'g') --- ``` --- This option cannot be set from a `modeline` or in the `sandbox`, for --- security reasons. @@ -727,9 +733,10 @@ vim.go.cd = vim.go.cdpath --- Only non-printable keys are allowed. --- The key can be specified as a single character, but it is difficult to --- type. The preferred way is to use the <> notation. Examples: ---- ``` ---- :exe "set cedit=\\" ---- :exe "set cedit=\\" +--- +--- ```vim +--- exe "set cedit=\\" +--- exe "set cedit=\\" --- ``` --- `Nvi` also has this option, but it only uses the first character. --- See `cmdwin`. @@ -763,7 +770,8 @@ vim.bo.channel = vim.o.channel --- is done internally by Vim, 'charconvert' is not used for this. --- Also used for Unicode conversion. --- Example: ---- ``` +--- +--- ```vim --- set charconvert=CharConvert() --- fun CharConvert() --- system("recode " @@ -829,7 +837,8 @@ vim.bo.cino = vim.bo.cinoptions --- Keywords that are interpreted as a C++ scope declaration by `cino-g`. --- Useful e.g. for working with the Qt framework that defines additional --- scope declarations "signals", "public slots" and "private slots": ---- ``` +--- +--- ```vim --- set cinscopedecls+=signals,public\ slots,private\ slots --- ``` --- @@ -916,10 +925,12 @@ vim.go.cwh = vim.go.cmdwinheight --- text. Will make screen redrawing slower. --- The screen column can be an absolute number, or a number preceded with --- '+' or '-', which is added to or subtracted from 'textwidth'. ---- ``` ---- :set cc=+1 " highlight column after 'textwidth' ---- :set cc=+1,+2,+3 " highlight three columns after 'textwidth' ---- :hi ColorColumn ctermbg=lightgrey guibg=lightgrey +--- +--- ```vim +--- +--- set cc=+1 " highlight column after 'textwidth' +--- set cc=+1,+2,+3 " highlight three columns after 'textwidth' +--- hi ColorColumn ctermbg=lightgrey guibg=lightgrey --- ``` --- --- When 'textwidth' is zero then the items with '-' and '+' are not used. @@ -941,8 +952,9 @@ vim.wo.cc = vim.wo.colorcolumn --- the GUI it is always possible and Vim limits the number of columns to --- what fits on the screen. You can use this command to get the widest --- window possible: ---- ``` ---- :set columns=9999 +--- +--- ```vim +--- set columns=9999 --- ``` --- Minimum value is 12, maximum value is 10000. --- @@ -985,8 +997,9 @@ vim.bo.cms = vim.bo.commentstring --- kspell use the currently active spell checking `spell` --- k{dict} scan the file {dict}. Several "k" flags can be given, --- patterns are valid too. For example: ---- ``` ---- :set cpt=k/usr/dict/*,k~/spanish +--- +--- ```vim +--- set cpt=k/usr/dict/*,k~/spanish --- ``` --- s scan the files given with the 'thesaurus' option --- s{tsr} scan the file {tsr}. Several "s" flags can be given, patterns @@ -1419,7 +1432,8 @@ vim.wo.crb = vim.wo.cursorbind --- slower. --- If you only want the highlighting in the current window you can use --- these autocommands: ---- ``` +--- +--- ```vim --- au WinLeave * set nocursorline nocursorcolumn --- au WinEnter * set cursorline cursorcolumn --- ``` @@ -1502,7 +1516,8 @@ vim.go.debug = vim.o.debug --- ``` --- When using the ":set" command, you need to double the backslashes! --- To avoid that use `:let` with a single quote string: ---- ``` +--- +--- ```vim --- let &l:define = '^\s*\ze\k\+\s*=\s*function(' --- ``` --- @@ -1681,11 +1696,12 @@ vim.go.dex = vim.go.diffexpr --- histogram histogram diff algorithm --- --- Examples: ---- ``` ---- :set diffopt=internal,filler,context:4 ---- :set diffopt= ---- :set diffopt=internal,filler,foldcolumn:3 ---- :set diffopt-=internal " do NOT use the internal diff parser +--- +--- ```vim +--- set diffopt=internal,filler,context:4 +--- set diffopt= +--- set diffopt=internal,filler,foldcolumn:3 +--- set diffopt-=internal " do NOT use the internal diff parser --- ``` --- --- @@ -1736,8 +1752,9 @@ vim.go.dg = vim.go.digraph --- - Environment variables are expanded `:set_env`. --- - Careful with '\' characters, type one before a space, type two to --- get one in the option (see `option-backslash`), for example: ---- ``` ---- :set dir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces +--- +--- ```vim +--- set dir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces --- ``` --- --- Editing the same file twice will result in a warning. Using "/tmp" on @@ -1924,8 +1941,9 @@ vim.go.efm = vim.go.errorformat --- When set to "all" or when "all" is one of the items, all autocommand --- events are ignored, autocommands will not be executed. --- Otherwise this is a comma-separated list of event names. Example: ---- ``` ---- :set ei=WinEnter,WinLeave +--- +--- ```vim +--- set ei=WinEnter,WinLeave --- ``` --- --- @@ -2021,7 +2039,8 @@ vim.bo.fenc = vim.bo.fileencoding --- "ucs-bom", which requires the BOM to be present). If you prefer --- another encoding use an BufReadPost autocommand event to test if your --- preferred encoding is to be used. Example: ---- ``` +--- +--- ```vim --- au BufReadPost * if search('\S', 'w') == 0 | --- \ set fenc=iso-2022-jp | endif --- ``` @@ -2031,8 +2050,9 @@ vim.bo.fenc = vim.bo.fileencoding --- not used. --- Note that 'fileencodings' is not used for a new file, the global value --- of 'fileencoding' is used instead. You can set it with: ---- ``` ---- :setglobal fenc=iso-8859-2 +--- +--- ```vim +--- setglobal fenc=iso-8859-2 --- ``` --- This means that a non-existing file may get a different encoding than --- an empty file. @@ -2156,14 +2176,12 @@ vim.go.fic = vim.go.fileignorecase --- this use the ":filetype on" command. `:filetype` --- Setting this option to a different value is most useful in a modeline, --- for a file for which the file type is not automatically recognized. ---- Example, for in an IDL file: ---- ``` +--- Example, for in an IDL file: >c --- /* vim: set filetype=idl : */ --- ``` --- `FileType` `filetypes` --- When a dot appears in the value then this separates two filetype ---- names. Example: ---- ``` +--- names. Example: >c --- /* vim: set filetype=c.doxygen : */ --- ``` --- This will use the "c" filetype first, then the "doxygen" filetype. @@ -2216,8 +2234,9 @@ vim.bo.ft = vim.bo.filetype --- default to single-byte alternatives. --- --- Example: ---- ``` ---- :set fillchars=stl:\ ,stlnc:\ ,vert:│,fold:·,diff:- +--- +--- ```vim +--- set fillchars=stl:\ ,stlnc:\ ,vert:│,fold:·,diff:- --- ``` --- --- For the "stl", "stlnc", "foldopen", "foldclose" and "foldsep" items @@ -2475,8 +2494,9 @@ vim.wo.fdt = vim.wo.foldtext --- it yet! --- --- Example: ---- ``` ---- :set formatexpr=mylang#Format() +--- +--- ```vim +--- set formatexpr=mylang#Format() --- ``` --- This will invoke the mylang#Format() function in the --- autoload/mylang.vim file in 'runtimepath'. `autoload` @@ -2492,7 +2512,8 @@ vim.wo.fdt = vim.wo.foldtext --- --- If the expression starts with s: or ``, then it is replaced with --- the script ID (`local-function`). Example: ---- ``` +--- +--- ```vim --- set formatexpr=s:MyFormatExpr() --- set formatexpr=SomeFormatExpr() --- ``` @@ -2618,8 +2639,9 @@ vim.go.gfm = vim.go.grepformat --- `option-backslash` about including spaces and backslashes. --- When your "grep" accepts the "-H" argument, use this to make ":grep" --- also work well with a single file: ---- ``` ---- :set grepprg=grep\ -nH +--- +--- ```vim +--- set grepprg=grep\ -nH --- ``` --- Special value: When 'grepprg' is set to "internal" the `:grep` command --- works like `:vimgrep`, `:lgrep` like `:lvimgrep`, `:grepadd` like @@ -2641,12 +2663,14 @@ vim.go.gp = vim.go.grepprg --- terminals. See `tui-cursor-shape`. --- --- To disable cursor-styling, reset the option: ---- ``` ---- :set guicursor= +--- +--- ```vim +--- set guicursor= --- ``` --- To enable mode shapes, "Cursor" highlight, and blinking: ---- ``` ---- :set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50 +--- +--- ```vim +--- set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50 --- \,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor --- \,sm:block-blinkwait175-blinkoff150-blinkon175 --- ``` @@ -2680,8 +2704,9 @@ vim.go.gp = vim.go.grepprg --- the cursor is shown and blinkoff is the time that the --- cursor is not shown. Times are in msec. When one of --- the numbers is zero, there is no blinking. E.g.: ---- ``` ---- :set guicursor=n:blinkon0 +--- +--- ```vim +--- set guicursor=n:blinkon0 --- ``` --- - Default is "blinkon0" for each mode. --- {group-name} @@ -2721,9 +2746,10 @@ vim.go.gp = vim.go.grepprg --- blinking: "a:blinkon0" --- --- Examples of cursor highlighting: ---- ``` ---- :highlight Cursor gui=reverse guifg=NONE guibg=NONE ---- :highlight Cursor gui=NONE guifg=bg guibg=fg +--- +--- ```vim +--- highlight Cursor gui=reverse guifg=NONE guibg=NONE +--- highlight Cursor gui=NONE guifg=bg guibg=fg --- ``` --- --- @@ -2743,8 +2769,9 @@ vim.go.gcr = vim.go.guicursor --- precede it with a backslash. Setting an option requires an extra --- backslash before a space and a backslash. See also --- `option-backslash`. For example: ---- ``` ---- :set guifont=Screen15,\ 7x13,font\\,with\\,commas +--- +--- ```vim +--- set guifont=Screen15,\ 7x13,font\\,with\\,commas --- ``` --- will make Vim try to use the font "Screen15" first, and if it fails it --- will try to use "7x13" and then "font,with,commas" instead. @@ -2757,16 +2784,18 @@ vim.go.gcr = vim.go.guicursor --- will try to find the related bold and italic fonts. --- --- For Win32 and Mac OS: ---- ``` ---- :set guifont=* +--- +--- ```vim +--- set guifont=* --- ``` --- will bring up a font requester, where you can pick the font you want. --- --- The font name depends on the GUI used. --- --- For Mac OSX you can use something like this: ---- ``` ---- :set guifont=Monaco:h10 +--- +--- ```vim +--- set guifont=Monaco:h10 --- ``` --- *E236* --- Note that the fonts must be mono-spaced (all characters have the same @@ -2793,9 +2822,10 @@ vim.go.gcr = vim.go.guicursor --- - A '_' can be used in the place of a space, so you don't need to use --- backslashes to escape the spaces. --- - Examples: ---- ``` ---- :set guifont=courier_new:h12:w5:b:cRUSSIAN ---- :set guifont=Andale_Mono:h7.5:w4.5 +--- +--- ```vim +--- set guifont=courier_new:h12:w5:b:cRUSSIAN +--- set guifont=Andale_Mono:h7.5:w4.5 --- ``` --- --- @@ -2949,8 +2979,9 @@ vim.go.gtl = vim.go.guitablabel --- pages line. When empty Vim will use a default tooltip. --- This option is otherwise just like 'guitablabel' above. --- You can include a line break. Simplest method is to use `:let`: ---- ``` ---- :let &guitabtooltip = "line one\nline two" +--- +--- ```vim +--- let &guitabtooltip = "line one\nline two" --- ``` --- --- @@ -2994,8 +3025,9 @@ vim.go.hh = vim.go.helpheight --- another language, but that will only find tags that exist in that --- language and not in the English help. --- Example: ---- ``` ---- :set helplang=de,it +--- +--- ```vim +--- set helplang=de,it --- ``` --- This will first search German, then Italian and finally English help --- files. @@ -3131,8 +3163,9 @@ vim.go.imd = vim.go.imdisable --- 2 :lmap is off and IM is ON --- To always reset the option to zero when leaving Insert mode with --- this can be used: ---- ``` ---- :inoremap :set iminsert=0 +--- +--- ```vim +--- inoremap :set iminsert=0 --- ``` --- This makes :lmap and IM turn off automatically when leaving Insert --- mode. @@ -3206,15 +3239,17 @@ vim.go.inc = vim.go.include --- Expression to be used to transform the string found with the 'include' --- option to a file name. Mostly useful to change "." to "/" for Java: ---- ``` ---- :setlocal includeexpr=substitute(v:fname,'\\.','/','g') +--- +--- ```vim +--- setlocal includeexpr=substitute(v:fname,'\\.','/','g') --- ``` --- The "v:fname" variable will be set to the file name that was detected. --- Note the double backslash: the `:set` command first halves them, then --- one remains in the value, where "\." matches a dot literally. For --- simple character replacements `tr()` avoids the need for escaping: ---- ``` ---- :setlocal includeexpr=tr(v:fname,'.','/') +--- +--- ```vim +--- setlocal includeexpr=tr(v:fname,'.','/') --- ``` --- --- Also used for the `gf` command if an unmodified file name can't be @@ -3223,7 +3258,8 @@ vim.go.inc = vim.go.include --- --- If the expression starts with s: or ``, then it is replaced with --- the script ID (`local-function`). Example: ---- ``` +--- +--- ```vim --- setlocal includeexpr=s:MyIncludeExpr(v:fname) --- setlocal includeexpr=SomeIncludeExpr(v:fname) --- ``` @@ -3262,7 +3298,8 @@ vim.bo.inex = vim.bo.includeexpr --- If you don't want to turn 'hlsearch' on, but want to highlight all --- matches while searching, you can turn on and off 'hlsearch' with --- autocmd. Example: ---- ``` +--- +--- ```vim --- augroup vimrc-incsearch-highlight --- autocmd! --- autocmd CmdlineEnter /,\? :set hlsearch @@ -3295,7 +3332,8 @@ vim.go.is = vim.go.incsearch --- --- If the expression starts with s: or ``, then it is replaced with --- the script ID (`local-function`). Example: ---- ``` +--- +--- ```vim --- set indentexpr=s:MyIndentExpr() --- set indentexpr=SomeIndentExpr() --- ``` @@ -3311,8 +3349,9 @@ vim.go.is = vim.go.incsearch --- not change the text, jump to another window, etc. Afterwards the --- cursor position is always restored, thus the cursor may be moved. --- Normally this option would be set to call a function: ---- ``` ---- :set indentexpr=GetMyIndent() +--- +--- ```vim +--- set indentexpr=GetMyIndent() --- ``` --- Error messages will be suppressed, unless the 'debug' option contains --- "msg". @@ -3540,9 +3579,10 @@ vim.go.km = vim.go.keymodel --- a [count] for the "K" command to a section number. --- See `option-backslash` about including spaces and backslashes. --- Example: ---- ``` ---- :set keywordprg=man\ -s ---- :set keywordprg=:Man +--- +--- ```vim +--- set keywordprg=man\ -s +--- set keywordprg=:Man --- ``` --- This option cannot be set from a `modeline` or in the `sandbox`, for --- security reasons. @@ -3569,12 +3609,14 @@ vim.go.kp = vim.go.keywordprg --- security reasons. --- --- Example (for Greek, in UTF-8): *greek* ---- ``` ---- :set langmap=ΑA,ΒB,ΨC,ΔD,ΕE,ΦF,ΓG,ΗH,ΙI,ΞJ,ΚK,ΛL,ΜM,ΝN,ΟO,ΠP,QQ,ΡR,ΣS,ΤT,ΘU,ΩV,WW,ΧX,ΥY,ΖZ,αa,βb,ψc,δd,εe,φf,γg,ηh,ιi,ξj,κk,λl,μm,νn,οo,πp,qq,ρr,σs,τt,θu,ωv,ςw,χx,υy,ζz +--- +--- ```vim +--- set langmap=ΑA,ΒB,ΨC,ΔD,ΕE,ΦF,ΓG,ΗH,ΙI,ΞJ,ΚK,ΛL,ΜM,ΝN,ΟO,ΠP,QQ,ΡR,ΣS,ΤT,ΘU,ΩV,WW,ΧX,ΥY,ΖZ,αa,βb,ψc,δd,εe,φf,γg,ηh,ιi,ξj,κk,λl,μm,νn,οo,πp,qq,ρr,σs,τt,θu,ωv,ςw,χx,υy,ζz --- ``` --- Example (exchanges meaning of z and y for commands): ---- ``` ---- :set langmap=zy,yz,ZY,YZ +--- +--- ```vim +--- set langmap=zy,yz,ZY,YZ --- ``` --- --- The 'langmap' option is a list of parts, separated with commas. Each @@ -3607,28 +3649,32 @@ vim.go.lmap = vim.go.langmap --- Language to use for menu translation. Tells which file is loaded --- from the "lang" directory in 'runtimepath': ---- ``` +--- +--- ```vim --- "lang/menu_" .. &langmenu .. ".vim" --- ``` --- (without the spaces). For example, to always use the Dutch menus, no --- matter what $LANG is set to: ---- ``` ---- :set langmenu=nl_NL.ISO_8859-1 +--- +--- ```vim +--- set langmenu=nl_NL.ISO_8859-1 --- ``` --- When 'langmenu' is empty, `v:lang` is used. --- Only normal file name characters can be used, `/\*?[|<>` are illegal. --- If your $LANG is set to a non-English language but you do want to use --- the English menus: ---- ``` ---- :set langmenu=none +--- +--- ```vim +--- set langmenu=none --- ``` --- This option must be set before loading menus, switching on filetype --- detection or syntax highlighting. Once the menus are defined setting --- this option has no effect. But you could do this: ---- ``` ---- :source $VIMRUNTIME/delmenu.vim ---- :set langmenu=de_DE.ISO_8859-1 ---- :source $VIMRUNTIME/menu.vim +--- +--- ```vim +--- source $VIMRUNTIME/delmenu.vim +--- set langmenu=de_DE.ISO_8859-1 +--- source $VIMRUNTIME/menu.vim --- ``` --- Warning: This deletes all menus that you defined yourself! --- @@ -3701,8 +3747,9 @@ vim.wo.lbr = vim.wo.linebreak --- to use the size for the GUI, put the command in your `gvimrc` file. --- Vim limits the number of lines to what fits on the screen. You can --- use this command to get the tallest window possible: ---- ``` ---- :set lines=999 +--- +--- ```vim +--- set lines=999 --- ``` --- Minimum value is 2, maximum value is 1000. --- @@ -3771,8 +3818,9 @@ vim.go.lw = vim.go.lispwords --- The cursor is displayed at the start of the space a Tab character --- occupies, not at the end as usual in Normal mode. To get this cursor --- position while displaying Tabs with spaces, use: ---- ``` ---- :set list lcs=tab:\ \ +--- +--- ```vim +--- set list lcs=tab:\ \ --- ``` --- --- Note that list mode will also affect formatting (set with 'textwidth' @@ -3837,8 +3885,9 @@ vim.wo.list = vim.o.list --- leading spaces are blank. Overrides the "space" and --- "multispace" settings for leading spaces. You can --- combine it with "tab:", for example: ---- ``` ---- :set listchars+=tab:>-,lead:. +--- +--- ```vim +--- set listchars+=tab:>-,lead:. --- ``` --- --- *lcs-leadmultispace* @@ -3878,7 +3927,8 @@ vim.wo.list = vim.o.list --- be used. All characters must be single width. --- --- Each character can be specified as hex: ---- ``` +--- +--- ```vim --- set listchars=eol:\\x24 --- set listchars=eol:\\u21b5 --- set listchars=eol:\\U000021b5 @@ -3887,10 +3937,11 @@ vim.wo.list = vim.o.list --- must be exactly 2 for \\x, 4 for \\u and 8 for \\U. --- --- Examples: ---- ``` ---- :set lcs=tab:>-,trail:- ---- :set lcs=tab:>-,eol:<,nbsp:% ---- :set lcs=extends:>,precedes:< +--- +--- ```vim +--- set lcs=tab:>-,trail:- +--- set lcs=tab:>-,eol:<,nbsp:% +--- set lcs=extends:>,precedes:< --- ``` --- `hl-NonText` highlighting will be used for "eol", "extends" and --- "precedes". `hl-Whitespace` for "nbsp", "space", "tab", "multispace", @@ -3955,8 +4006,9 @@ vim.go.mef = vim.go.makeef --- This would be mostly useful when you use MS-Windows. If iconv is --- enabled, setting 'makeencoding' to "char" has the same effect as --- setting to the system locale encoding. Example: ---- ``` ---- :set makeencoding=char " system locale is used +--- +--- ```vim +--- set makeencoding=char " system locale is used --- ``` --- --- @@ -3977,13 +4029,15 @@ vim.go.menc = vim.go.makeencoding --- Note that a '|' must be escaped twice: once for ":set" and once for --- the interpretation of a command. When you use a filter called --- "myfilter" do it like this: ---- ``` ---- :set makeprg=gmake\ \\\|\ myfilter +--- +--- ```vim +--- set makeprg=gmake\ \\\|\ myfilter --- ``` --- The placeholder "$*" can be given (even multiple times) to specify --- where the arguments will be included, for example: ---- ``` ---- :set makeprg=latex\ \\\\nonstopmode\ \\\\input\\{$*} +--- +--- ```vim +--- set makeprg=latex\ \\\\nonstopmode\ \\\\input\\{$*} --- ``` --- This option cannot be set from a `modeline` or in the `sandbox`, for --- security reasons. @@ -4003,13 +4057,15 @@ vim.go.mp = vim.go.makeprg --- The characters must be separated by a colon. --- The pairs must be separated by a comma. Example for including '<' and --- '>' (for HTML): ---- ``` ---- :set mps+=<:> +--- +--- ```vim +--- set mps+=<:> --- ``` --- A more exotic example, to jump between the '=' and ';' in an --- assignment, useful for languages like C and Java: ---- ``` ---- :au FileType c,cpp,java set mps+==:; +--- +--- ```vim +--- au FileType c,cpp,java set mps+==:; --- ``` --- For a more advanced way of using "%", see the matchit.vim plugin in --- the $VIMRUNTIME/plugin directory. `add-local-help` @@ -4117,8 +4173,9 @@ vim.go.mis = vim.go.menuitems --- The languages for which these numbers are important are Italian and --- Hungarian. The default works for when you have about 512 Mbyte. If --- you have 1 Gbyte you could use: ---- ``` ---- :set mkspellmem=900000,3000,800 +--- +--- ```vim +--- set mkspellmem=900000,3000,800 --- ``` --- If you have less than 512 Mbyte `:mkspell` may fail for some --- languages, no matter what you set 'mkspellmem' to. @@ -4213,8 +4270,9 @@ vim.go.more = vim.o.more --- Enables mouse support. For example, to enable the mouse in Normal mode --- and Visual mode: ---- ``` ---- :set mouse=nv +--- +--- ```vim +--- set mouse=nv --- ``` --- --- To temporarily disable mouse support, hold the shift key while using @@ -4306,19 +4364,20 @@ vim.go.mh = vim.go.mousehide --- See `mouse-overview`. But mappings are NOT used for modeless selection. --- --- Example: ---- ``` ---- :map ---- :map ---- :map ---- :map <2-S-LeftMouse> <2-RightMouse> ---- :map <2-S-LeftDrag> <2-RightDrag> ---- :map <2-S-LeftRelease> <2-RightRelease> ---- :map <3-S-LeftMouse> <3-RightMouse> ---- :map <3-S-LeftDrag> <3-RightDrag> ---- :map <3-S-LeftRelease> <3-RightRelease> ---- :map <4-S-LeftMouse> <4-RightMouse> ---- :map <4-S-LeftDrag> <4-RightDrag> ---- :map <4-S-LeftRelease> <4-RightRelease> +--- +--- ```vim +--- map +--- map +--- map +--- map <2-S-LeftMouse> <2-RightMouse> +--- map <2-S-LeftDrag> <2-RightDrag> +--- map <2-S-LeftRelease> <2-RightRelease> +--- map <3-S-LeftMouse> <3-RightMouse> +--- map <3-S-LeftDrag> <3-RightDrag> +--- map <3-S-LeftRelease> <3-RightRelease> +--- map <4-S-LeftMouse> <4-RightMouse> +--- map <4-S-LeftDrag> <4-RightDrag> +--- map <4-S-LeftRelease> <4-RightRelease> --- ``` --- --- Mouse commands requiring the CTRL modifier can be simulated by typing @@ -4358,8 +4417,9 @@ vim.go.mousemev = vim.go.mousemoveevent --- a count of 0. --- --- Example: ---- ``` ---- :set mousescroll=ver:5,hor:2 +--- +--- ```vim +--- set mousescroll=ver:5,hor:2 --- ``` --- Will make Nvim scroll 5 lines at a time when scrolling vertically, and --- scroll 2 columns at a time when scrolling horizontally. @@ -4422,8 +4482,9 @@ vim.go.mousescroll = vim.o.mousescroll --- pointer. --- --- Example: ---- ``` ---- :set mouseshape=s:udsizing,m:no +--- +--- ```vim +--- set mouseshape=s:udsizing,m:no --- ``` --- will make the mouse turn to a sizing arrow over the status lines and --- indicate no input when the hit-enter prompt is displayed (since @@ -4627,28 +4688,33 @@ vim.go.pm = vim.go.patchmode --- starting with "/", "./" or "../"). The directories in the 'path' --- option may be relative or absolute. --- - Use commas to separate directory names: ---- ``` ---- :set path=.,/usr/local/include,/usr/include +--- +--- ```vim +--- set path=.,/usr/local/include,/usr/include --- ``` --- - Spaces can also be used to separate directory names. To have a --- space in a directory name, precede it with an extra backslash, and --- escape the space: ---- ``` ---- :set path=.,/dir/with\\\ space +--- +--- ```vim +--- set path=.,/dir/with\\\ space --- ``` --- - To include a comma in a directory name precede it with an extra --- backslash: ---- ``` ---- :set path=.,/dir/with\\,comma +--- +--- ```vim +--- set path=.,/dir/with\\,comma --- ``` --- - To search relative to the directory of the current file, use: ---- ``` ---- :set path=. +--- +--- ```vim +--- set path=. --- ``` --- - To search in the current directory use an empty string between two --- commas: ---- ``` ---- :set path=,, +--- +--- ```vim +--- set path=,, --- ``` --- - A directory name may end in a ':' or '/'. --- - Environment variables are expanded `:set_env`. @@ -4657,12 +4723,14 @@ vim.go.pm = vim.go.patchmode --- - Search upwards and downwards in a directory tree using "*", "**" and --- ";". See `file-searching` for info and syntax. --- - Careful with '\' characters, type two to get one in the option: ---- ``` ---- :set path=.,c:\\include +--- +--- ```vim +--- set path=.,c:\\include --- ``` --- Or just use '/' instead: ---- ``` ---- :set path=.,c:/include +--- +--- ```vim +--- set path=.,c:/include --- ``` --- Don't forget "." or files won't even be found in the same directory as --- the file! @@ -4673,18 +4741,21 @@ vim.go.pm = vim.go.patchmode --- The use of `:set+=` and `:set-=` is preferred when adding or removing --- directories from the list. This avoids problems when a future version --- uses another default. To remove the current directory use: ---- ``` ---- :set path-= +--- +--- ```vim +--- set path-= --- ``` --- To add the current directory use: ---- ``` ---- :set path+= +--- +--- ```vim +--- set path+= --- ``` --- To use an environment variable, you probably need to replace the --- separator. Here is an example to append $INCL, in which directory --- names are separated with a semi-colon: ---- ``` ---- :let &path = &path .. "," .. substitute($INCL, ';', ',', 'g') +--- +--- ```vim +--- let &path = &path .. "," .. substitute($INCL, ';', ',', 'g') --- ``` --- Replace the ';' with a ':' or whatever separator is used. Note that --- this doesn't work when $INCL contains a comma or white space. @@ -4742,9 +4813,11 @@ vim.wo.pvw = vim.wo.previewwindow --- It is possible to override the level for individual highlights within --- the popupmenu using `highlight-blend`. For instance, to enable --- transparency but force the current selected element to be fully opaque: ---- ``` ---- :set pumblend=15 ---- :hi PmenuSel blend=0 +--- +--- ```vim +--- +--- set pumblend=15 +--- hi PmenuSel blend=0 --- ``` --- --- UI-dependent. Works best with RGB colors. 'termguicolors' @@ -5015,8 +5088,9 @@ vim.go.ru = vim.go.ruler --- The default ruler width is 17 characters. To make the ruler 15 --- characters wide, put "%15(" at the start and "%)" at the end. --- Example: ---- ``` ---- :set rulerformat=%15(%c%V\ %p%%%) +--- +--- ```vim +--- set rulerformat=%15(%c%V\ %p%%%) --- ``` --- --- @@ -5083,8 +5157,9 @@ vim.go.ruf = vim.go.rulerformat --- wildcards. --- See `:runtime`. --- Example: ---- ``` ---- :set runtimepath=~/vimruntime,/mygroup/vim,$VIMRUNTIME +--- +--- ```vim +--- set runtimepath=~/vimruntime,/mygroup/vim,$VIMRUNTIME --- ``` --- This will use the directory "~/vimruntime" first (containing your --- personal Nvim runtime files), then "/mygroup/vim", and finally @@ -5165,7 +5240,8 @@ vim.go.sj = vim.go.scrolljump --- when long lines wrap). --- After using the local value, go back the global value with one of --- these two: ---- ``` +--- +--- ```vim --- setlocal scrolloff< --- setlocal scrolloff=-1 --- ``` @@ -5394,8 +5470,9 @@ vim.go.ssop = vim.go.sessionoptions --- contents size) = 10253 bytes. --- --- Example: ---- ``` ---- :set shada='50,<1000,s100,:0,n~/nvim/shada +--- +--- ```vim +--- set shada='50,<1000,s100,:0,n~/nvim/shada --- ``` --- --- '50 Marks will be remembered for the last 50 files you @@ -5446,14 +5523,16 @@ vim.go.sdf = vim.go.shadafile --- --- If the name of the shell contains a space, you need to enclose it in --- quotes. Example with quotes: ---- ``` ---- :set shell=\"c:\program\ files\unix\sh.exe\"\ -f +--- +--- ```vim +--- set shell=\"c:\program\ files\unix\sh.exe\"\ -f --- ``` --- Note the backslash before each quote (to avoid starting a comment) and --- each space (to avoid ending the option value), so better use `:let-&` --- like this: ---- ``` ---- :let &shell='"C:\Program Files\unix\sh.exe" -f' +--- +--- ```vim +--- let &shell='"C:\Program Files\unix\sh.exe" -f' --- ``` --- Also note that the "-f" is not inside the quotes, because it is not --- part of the command name. @@ -5478,7 +5557,8 @@ vim.go.sdf = vim.go.shadafile --- unescaping, so to keep yourself sane use `:let-&` like shown above. --- *shell-powershell* --- To use PowerShell: ---- ``` +--- +--- ```vim --- let &shell = executable('pwsh') ? 'pwsh' : 'powershell' --- let &shellcmdflag = '-NoLogo -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new();$PSDefaultParameterValues[''Out-File:Encoding'']=''utf8'';Remove-Alias -Force -ErrorAction SilentlyContinue tee;' --- let &shellredir = '2>&1 | %%{ "$_" } | Out-File %s; exit $LastExitCode' @@ -5603,7 +5683,8 @@ vim.go.srr = vim.go.shellredir --- any file for best results. This might change in the future. --- 'shellslash' only works when a backslash can be used as a path --- separator. To test if this is so use: ---- ``` +--- +--- ```vim --- if exists('+shellslash') --- ``` --- Also see 'completeslash'. @@ -5739,9 +5820,10 @@ vim.go.shm = vim.go.shortmess --- String to put at the start of lines that have been wrapped. Useful --- values are "> " or "+++ ": ---- ``` ---- :let &showbreak = "> " ---- :let &showbreak = '+++ ' +--- +--- ```vim +--- let &showbreak = "> " +--- let &showbreak = '+++ ' --- ``` --- Only printable single-cell characters are allowed, excluding and --- comma (in a future version the comma might be used to separate the @@ -5752,8 +5834,9 @@ vim.go.shm = vim.go.shortmess --- "n" flag to 'cpoptions'. --- A window-local value overrules a global value. If the global value is --- set and you want no value in the current window use NONE: ---- ``` ---- :setlocal showbreak=NONE +--- +--- ```vim +--- setlocal showbreak=NONE --- ``` --- --- @@ -5885,7 +5968,8 @@ vim.go.ss = vim.go.sidescroll --- close to the beginning of the line. --- After using the local value, go back the global value with one of --- these two: ---- ``` +--- +--- ```vim --- setlocal sidescrolloff< --- setlocal sidescrolloff=-1 --- ``` @@ -5893,9 +5977,11 @@ vim.go.ss = vim.go.sidescroll --- Example: Try this together with 'sidescroll' and 'listchars' as --- in the following example to never allow the cursor to move --- onto the "extends" character: ---- ``` ---- :set nowrap sidescroll=1 listchars=extends:>,precedes:< ---- :set sidescrolloff=1 +--- +--- ```vim +--- +--- set nowrap sidescroll=1 listchars=extends:>,precedes:< +--- set sidescrolloff=1 --- ``` --- --- @@ -6076,7 +6162,8 @@ vim.bo.spf = vim.bo.spellfile --- A comma-separated list of word list names. When the 'spell' option is --- on spellchecking will be done for these languages. Example: ---- ``` +--- +--- ```vim --- set spelllang=en_us,nl,medical --- ``` --- This means US English, Dutch and medical words are recognized. Words @@ -6194,8 +6281,9 @@ vim.bo.spo = vim.bo.spelloptions --- --- Only one of "best", "double" or "fast" may be used. The others may --- appear several times in any order. Example: ---- ``` ---- :set sps=file:~/.config/nvim/sugg,best,expr:MySuggest() +--- +--- ```vim +--- set sps=file:~/.config/nvim/sugg,best,expr:MySuggest() --- ``` --- --- This option cannot be set from a `modeline` or in the `sandbox`, for @@ -6293,21 +6381,21 @@ vim.go.sol = vim.go.startofline --- --- ```vim --- " Relative number with bar separator and click handlers: ---- :set statuscolumn=%@SignCb@%s%=%T%@NumCb@%r│%T +--- set statuscolumn=%@SignCb@%s%=%T%@NumCb@%r│%T --- --- " Right aligned relative cursor line number: ---- :let &stc='%=%{v:relnum?v:relnum:v:lnum} ' +--- let &stc='%=%{v:relnum?v:relnum:v:lnum} ' --- --- " Line numbers in hexadecimal for non wrapped part of lines: ---- :let &stc='%=%{v:virtnum>0?"":printf("%x",v:lnum)} ' +--- let &stc='%=%{v:virtnum>0?"":printf("%x",v:lnum)} ' --- --- " Human readable line numbers with thousands separator: ---- :let &stc='%{substitute(v:lnum,"\\d\\zs\\ze\\' +--- let &stc='%{substitute(v:lnum,"\\d\\zs\\ze\\' --- . '%(\\d\\d\\d\\)\\+$",",","g")}' --- --- " Both relative and absolute line numbers with different --- " highlighting for odd and even relative numbers: ---- :let &stc='%#NonText#%{&nu?v:lnum:""}' . +--- let &stc='%#NonText#%{&nu?v:lnum:""}' . --- '%=%{&rnu&&(v:lnum%2)?"\ ".v:relnum:""}' . --- '%#LineNr#%{&rnu&&!(v:lnum%2)?"\ ".v:relnum:""}' --- ``` @@ -6331,8 +6419,9 @@ vim.wo.stc = vim.wo.statuscolumn --- --- When the option starts with "%!" then it is used as an expression, --- evaluated and the result is used as the option value. Example: ---- ``` ---- :set statusline=%!MyStatusLine() +--- +--- ```vim +--- set statusline=%!MyStatusLine() --- ``` --- The *g:statusline_winid* variable will be set to the `window-ID` of the --- window that the status line belongs to. @@ -6415,7 +6504,8 @@ vim.wo.stc = vim.wo.statuscolumn --- The expression can contain the "}" character, the end of --- expression is denoted by "%}". --- For example: ---- ``` +--- +--- ```vim --- func! Stl_filename() abort --- return "%t" --- endfunc @@ -6484,8 +6574,9 @@ vim.wo.stc = vim.wo.statuscolumn --- not set) and a minwid is not set for the group, the whole group will --- become empty. This will make a group like the following disappear --- completely from the statusline when none of the flags are set. ---- ``` ---- :set statusline=...%(\ [%M%R%H]%)... +--- +--- ```vim +--- set statusline=...%(\ [%M%R%H]%)... --- ``` --- Beware that an expression is evaluated each and every time the status --- line is displayed. @@ -6518,35 +6609,42 @@ vim.wo.stc = vim.wo.statuscolumn --- --- Examples: --- Emulate standard status line with 'ruler' set ---- ``` ---- :set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P +--- +--- ```vim +--- set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P --- ``` --- Similar, but add ASCII value of char under the cursor (like "ga") ---- ``` ---- :set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P +--- +--- ```vim +--- set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P --- ``` --- Display byte count and byte value, modified flag in red. ---- ``` ---- :set statusline=%<%f%=\ [%1*%M%*%n%R%H]\ %-19(%3l,%02c%03V%)%O'%02b' ---- :hi User1 term=inverse,bold cterm=inverse,bold ctermfg=red +--- +--- ```vim +--- set statusline=%<%f%=\ [%1*%M%*%n%R%H]\ %-19(%3l,%02c%03V%)%O'%02b' +--- hi User1 term=inverse,bold cterm=inverse,bold ctermfg=red --- ``` --- Display a ,GZ flag if a compressed file is loaded ---- ``` ---- :set statusline=...%r%{VarExists('b:gzflag','\ [GZ]')}%h... +--- +--- ```vim +--- set statusline=...%r%{VarExists('b:gzflag','\ [GZ]')}%h... --- ``` --- In the `:autocmd`'s: ---- ``` ---- :let b:gzflag = 1 +--- +--- ```vim +--- let b:gzflag = 1 --- ``` --- And: ---- ``` ---- :unlet b:gzflag +--- +--- ```vim +--- unlet b:gzflag --- ``` --- And define this function: ---- ``` ---- :function VarExists(var, val) ---- : if exists(a:var) | return a:val | else | return '' | endif ---- :endfunction +--- +--- ```vim +--- function VarExists(var, val) +--- if exists(a:var) | return a:val | else | return '' | endif +--- endfunction --- ``` --- --- @@ -6577,8 +6675,9 @@ vim.go.su = vim.go.suffixes --- Comma-separated list of suffixes, which are used when searching for a --- file for the "gf", "[I", etc. commands. Example: ---- ``` ---- :set suffixesadd=.java +--- +--- ```vim +--- set suffixesadd=.java --- ``` --- --- @@ -6663,26 +6762,26 @@ vim.bo.smc = vim.bo.synmaxcol --- Otherwise this option does not always reflect the current syntax (the --- b:current_syntax variable does). --- This option is most useful in a modeline, for a file which syntax is ---- not automatically recognized. Example, in an IDL file: ---- ``` +--- not automatically recognized. Example, in an IDL file: >c --- /* vim: set syntax=idl : */ --- ``` --- When a dot appears in the value then this separates two filetype ---- names. Example: ---- ``` +--- names. Example: >c --- /* vim: set syntax=c.doxygen : */ --- ``` --- This will use the "c" syntax first, then the "doxygen" syntax. --- Note that the second one must be prepared to be loaded as an addition, --- otherwise it will be skipped. More than one dot may appear. --- To switch off syntax highlighting for the current file, use: ---- ``` ---- :set syntax=OFF +--- +--- ```vim +--- set syntax=OFF --- ``` --- To switch syntax highlighting on according to the current value of the --- 'filetype' option: ---- ``` ---- :set syntax=ON +--- +--- ```vim +--- set syntax=ON --- ``` --- What actually happens when setting the 'syntax' option is that the --- Syntax autocommand event is triggered with the value as argument. @@ -7112,15 +7211,17 @@ vim.go.titleold = vim.o.titleold --- This option cannot be set in a modeline when 'modelineexpr' is off. --- --- Example: ---- ``` ---- :auto BufEnter * let &titlestring = hostname() .. "/" .. expand("%:p") ---- :set title titlestring=%<%F%=%l/%L-%P titlelen=70 +--- +--- ```vim +--- auto BufEnter * let &titlestring = hostname() .. "/" .. expand("%:p") +--- set title titlestring=%<%F%=%l/%L-%P titlelen=70 --- ``` --- The value of 'titlelen' is used to align items in the middle or right --- of the available space. --- Some people prefer to have the file name first: ---- ``` ---- :set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:~:.:h\")})%)%(\ %a%) +--- +--- ```vim +--- set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:~:.:h\")})%)%(\ %a%) --- ``` --- Note the use of "%{ }" and an expression to get the path of the file, --- without the file name. The "%( %)" constructs are used to add a @@ -7205,7 +7306,8 @@ vim.bo.udf = vim.bo.undofile --- Nevertheless, a single change can already use a large amount of memory. --- Set to 0 for Vi compatibility: One level of undo and "u" undoes --- itself: ---- ``` +--- +--- ```vim --- set ul=0 --- ``` --- But you can also get Vi compatibility by including the 'u' flag in @@ -7213,7 +7315,8 @@ vim.bo.udf = vim.bo.undofile --- Also see `undo-two-ways`. --- Set to -1 for no undo at all. You might want to do this only for the --- current buffer: ---- ``` +--- +--- ```vim --- setlocal ul=-1 --- ``` --- This helps when you run out of memory for a single change. @@ -7285,8 +7388,9 @@ vim.go.ut = vim.go.updatetime --- For example, when editing assembly language files where statements --- start in the 9th column and comments in the 41st, it may be useful --- to use the following: ---- ``` ---- :set varsofttabstop=8,32,8 +--- +--- ```vim +--- set varsofttabstop=8,32,8 --- ``` --- This will set soft tabstops with 8 and 8 + 32 spaces, and 8 more --- for every column thereafter. @@ -7303,8 +7407,9 @@ vim.bo.vsts = vim.bo.varsofttabstop --- A list of the number of spaces that a in the file counts for, --- separated by commas. Each value corresponds to one tab, with the --- final value applying to all subsequent tabs. For example: ---- ``` ---- :set vartabstop=4,20,10,8 +--- +--- ```vim +--- set vartabstop=4,20,10,8 --- ``` --- This will make the first tab 4 spaces wide, the second 20 spaces, --- the third 10 spaces, and all following tabs 8 spaces. @@ -7459,8 +7564,9 @@ vim.go.warn = vim.o.warn --- [ Insert and Replace --- ] Insert and Replace --- For example: ---- ``` ---- :set ww=<,>,[,] +--- +--- ```vim +--- set ww=<,>,[,] --- ``` --- allows wrap only when cursor keys are used. --- When the movement keys are used in combination with a delete or change @@ -7489,8 +7595,9 @@ vim.go.ww = vim.go.whichwrap --- can be used, but hitting it twice in a row will still exit --- command-line as a failsafe measure. --- Although 'wc' is a number option, you can set it to a special key: ---- ``` ---- :set wc= +--- +--- ```vim +--- set wc= --- ``` --- --- @@ -7505,9 +7612,10 @@ vim.go.wc = vim.go.wildchar --- keys suitable for this option by looking at `ex-edit-index`. Normally --- you'll never actually type 'wildcharm', just use it in mappings that --- automatically invoke completion mode, e.g.: ---- ``` ---- :set wcm= ---- :cnoremap ss so $vim/sessions/*.vim +--- +--- ```vim +--- set wcm= +--- cnoremap ss so $vim/sessions/*.vim --- ``` --- Then after typing :ss you can use CTRL-P & CTRL-N. --- @@ -7524,8 +7632,9 @@ vim.go.wcm = vim.go.wildcharm --- The pattern is used like with `:autocmd`, see `autocmd-pattern`. --- Also see 'suffixes'. --- Example: ---- ``` ---- :set wildignore=*.o,*.obj +--- +--- ```vim +--- set wildignore=*.o,*.obj --- ``` --- The use of `:set+=` and `:set-=` is preferred when adding or removing --- a pattern from the list. This avoids problems when a future version @@ -7581,9 +7690,10 @@ vim.go.wic = vim.go.wildignorecase --- --- If you want and to move the cursor instead of selecting --- a different match, use this: ---- ``` ---- :cnoremap ---- :cnoremap +--- +--- ```vim +--- cnoremap +--- cnoremap --- ``` --- --- `hl-WildMenu` highlights the current match. @@ -7626,24 +7736,29 @@ vim.go.wmnu = vim.go.wildmenu --- current buffer). --- --- Examples: ---- ``` ---- :set wildmode=full +--- +--- ```vim +--- set wildmode=full --- ``` --- Complete first full match, next match, etc. (the default) ---- ``` ---- :set wildmode=longest,full +--- +--- ```vim +--- set wildmode=longest,full --- ``` --- Complete longest common string, then each full match ---- ``` ---- :set wildmode=list:full +--- +--- ```vim +--- set wildmode=list:full --- ``` --- List all matches and complete each full match ---- ``` ---- :set wildmode=list,full +--- +--- ```vim +--- set wildmode=list,full --- ``` --- List all matches without completing, then each full match ---- ``` ---- :set wildmode=longest,list +--- +--- ```vim +--- set wildmode=longest,list --- ``` --- Complete longest common string, then list alternatives. --- More info here: `cmdline-completion`. @@ -7781,7 +7896,8 @@ vim.wo.wfw = vim.wo.winfixwidth --- that ":all" will create only two windows. To avoid "vim -o 1 2 3 4" --- to create only two windows, set the option after startup is done, --- using the `VimEnter` event: ---- ``` +--- +--- ```vim --- au VimEnter * set winheight=999 --- ``` --- Minimum value is 1. @@ -7811,7 +7927,8 @@ vim.go.wh = vim.go.winheight --- message area cannot be overridden. --- --- Example: show a different color for non-current windows: ---- ``` +--- +--- ```vim --- set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC --- ``` --- @@ -7881,9 +7998,10 @@ vim.go.wiw = vim.go.winwidth --- The line will be broken in the middle of a word if necessary. See --- 'linebreak' to get the break at a word boundary. --- To make scrolling horizontally a bit more useful, try this: ---- ``` ---- :set sidescroll=5 ---- :set listchars+=precedes:<,extends:> +--- +--- ```vim +--- set sidescroll=5 +--- set listchars+=precedes:<,extends:> --- ``` --- See 'sidescroll', 'listchars' and `wrap-off`. --- This option can't be set from a `modeline` when the 'diff' option is -- cgit From db0ec84fb46b8235f8651d5aa25eb56a9b117eb5 Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Fri, 22 Dec 2023 11:38:02 +0100 Subject: feat(lsp): add type annotations for lsp.util.locations_to_items (#26694) Problem: luals reported many warnings Solution: Add type annotations --- runtime/lua/vim/lsp/util.lua | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index dc8fb25563..63c4c1e7fc 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1754,6 +1754,13 @@ local position_sort = sort_by_key(function(v) return { v.start.line, v.start.character } end) +---@class vim.lsp.util.LocationItem +---@field filename string +---@field lnum integer 1-indexed line number +---@field col integer 1-indexed column +---@field text string +---@field user_data lsp.Location|lsp.LocationLink + --- Returns the items with the byte position calculated correctly and in sorted --- order, for display in quickfix and location lists. --- @@ -1763,10 +1770,10 @@ end) --- The result can be passed to the {list} argument of |setqflist()| or --- |setloclist()|. --- ----@param locations table list of `Location`s or `LocationLink`s +---@param locations lsp.Location[]|lsp.LocationLink[] ---@param offset_encoding string offset_encoding for locations utf-8|utf-16|utf-32 --- default to first client of buffer ----@return table list of items +---@return vim.lsp.util.LocationItem[] list of items function M.locations_to_items(locations, offset_encoding) if offset_encoding == nil then vim.notify_once( @@ -1777,6 +1784,7 @@ function M.locations_to_items(locations, offset_encoding) end local items = {} + ---@type table local grouped = setmetatable({}, { __index = function(t, k) local v = {} @@ -1791,6 +1799,7 @@ function M.locations_to_items(locations, offset_encoding) table.insert(grouped[uri], { start = range.start, location = d }) end + ---@type string[] local keys = vim.tbl_keys(grouped) table.sort(keys) -- TODO(ashkan) I wish we could do this lazily. @@ -1799,16 +1808,13 @@ function M.locations_to_items(locations, offset_encoding) table.sort(rows, position_sort) local filename = vim.uri_to_fname(uri) - -- list of row numbers - local uri_rows = {} + local line_numbers = {} for _, temp in ipairs(rows) do - local pos = temp.start - local row = pos.line - table.insert(uri_rows, row) + table.insert(line_numbers, temp.start.line) end -- get all the lines for this uri - local lines = get_lines(vim.uri_to_bufnr(uri), uri_rows) + local lines = get_lines(vim.uri_to_bufnr(uri), line_numbers) for _, temp in ipairs(rows) do local pos = temp.start -- cgit From 92204b06e7365cf4c68e6ea8258dce801f0a5df9 Mon Sep 17 00:00:00 2001 From: Steven Arcangeli <506791+stevearc@users.noreply.github.com> Date: Fri, 22 Dec 2023 02:40:01 -0800 Subject: refactor(lsp): move glob parsing to util (#26519) refactor(lsp): move glob parsing to vim.glob Moving the logic for using vim.lpeg to create a match pattern from a glob into `vim.glob`. There are several places in the LSP spec that use globs, and it's very useful to have glob matching as a generally-available utility. --- runtime/lua/vim/_init_packages.lua | 1 + runtime/lua/vim/_meta.lua | 1 + runtime/lua/vim/glob.lua | 81 ++++++++++++++++++++++++++++++++ runtime/lua/vim/lsp/_dynamic.lua | 4 +- runtime/lua/vim/lsp/_watchfiles.lua | 93 +++---------------------------------- 5 files changed, 91 insertions(+), 89 deletions(-) create mode 100644 runtime/lua/vim/glob.lua (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_init_packages.lua b/runtime/lua/vim/_init_packages.lua index 4a961970cc..f8710f7fd7 100644 --- a/runtime/lua/vim/_init_packages.lua +++ b/runtime/lua/vim/_init_packages.lua @@ -55,6 +55,7 @@ vim._submodules = { inspect = true, version = true, fs = true, + glob = true, iter = true, re = true, text = true, diff --git a/runtime/lua/vim/_meta.lua b/runtime/lua/vim/_meta.lua index bb9ed722e2..4c50627fe4 100644 --- a/runtime/lua/vim/_meta.lua +++ b/runtime/lua/vim/_meta.lua @@ -11,6 +11,7 @@ vim.diagnostic = require('vim.diagnostic') vim.filetype = require('vim.filetype') vim.fs = require('vim.fs') vim.func = require('vim.func') +vim.glob = require('vim.glob') vim.health = require('vim.health') vim.highlight = require('vim.highlight') vim.iter = require('vim.iter') diff --git a/runtime/lua/vim/glob.lua b/runtime/lua/vim/glob.lua new file mode 100644 index 0000000000..731179d727 --- /dev/null +++ b/runtime/lua/vim/glob.lua @@ -0,0 +1,81 @@ +local lpeg = vim.lpeg + +local M = {} + +--- Parses a raw glob into an |lpeg| pattern. +--- +--- This uses glob semantics from LSP 3.17.0: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern +--- Glob patterns can have the following syntax: +--- `*` 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`) +---@param pattern string The raw glob pattern +---@return vim.lpeg.Pattern pattern An |lpeg| representation of the pattern +function M.to_lpeg(pattern) + local l = lpeg + + local P, S, V = lpeg.P, lpeg.S, lpeg.V + local C, Cc, Ct, Cf = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cf + + local pathsep = '/' + + local function class(inv, ranges) + for i, r in ipairs(ranges) do + ranges[i] = r[1] .. r[2] + end + local patt = l.R(unpack(ranges)) + if inv == '!' then + patt = P(1) - patt + end + return patt + end + + local function add(acc, a) + return acc + a + end + + local function mul(acc, m) + return acc * m + end + + local function star(stars, after) + return (-after * (l.P(1) - pathsep)) ^ #stars * after + end + + local function dstar(after) + return (-after * l.P(1)) ^ 0 * after + end + + local p = P({ + 'Pattern', + Pattern = V('Elem') ^ -1 * V('End'), + Elem = Cf( + (V('DStar') + V('Star') + V('Ques') + V('Class') + V('CondList') + V('Literal')) + * (V('Elem') + V('End')), + mul + ), + DStar = P('**') * (P(pathsep) * (V('Elem') + V('End')) + V('End')) / dstar, + Star = C(P('*') ^ 1) * (V('Elem') + V('End')) / star, + Ques = P('?') * Cc(l.P(1) - pathsep), + Class = P('[') * C(P('!') ^ -1) * Ct(Ct(C(1) * '-' * C(P(1) - ']')) ^ 1 * ']') / class, + CondList = P('{') * Cf(V('Cond') * (P(',') * V('Cond')) ^ 0, add) * '}', + -- TODO: '*' inside a {} condition is interpreted literally but should probably have the same + -- wildcard semantics it usually has. + -- Fixing this is non-trivial because '*' should match non-greedily up to "the rest of the + -- pattern" which in all other cases is the entire succeeding part of the pattern, but at the end of a {} + -- condition means "everything after the {}" where several other options separated by ',' may + -- exist in between that should not be matched by '*'. + Cond = Cf((V('Ques') + V('Class') + V('CondList') + (V('Literal') - S(',}'))) ^ 1, mul) + + Cc(l.P(0)), + Literal = P(1) / l.P, + End = P(-1) * Cc(l.P(-1)), + }) + + local lpeg_pattern = p:match(pattern) --[[@as vim.lpeg.Pattern?]] + return assert(lpeg_pattern, 'Invalid glob') +end + +return M diff --git a/runtime/lua/vim/lsp/_dynamic.lua b/runtime/lua/vim/lsp/_dynamic.lua index 04040e8e28..4bee58559f 100644 --- a/runtime/lua/vim/lsp/_dynamic.lua +++ b/runtime/lua/vim/lsp/_dynamic.lua @@ -1,4 +1,4 @@ -local wf = require('vim.lsp._watchfiles') +local glob = require('vim.glob') --- @class lsp.DynamicCapabilities --- @field capabilities table @@ -97,7 +97,7 @@ function M.match(bufnr, documentSelector) if matches and filter.scheme and not vim.startswith(uri, filter.scheme .. ':') then matches = false end - if matches and filter.pattern and not wf._match(filter.pattern, fname) then + if matches and filter.pattern and not glob.to_lpeg(filter.pattern):match(fname) then matches = false end if matches then diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua index 1fd112631d..af4cc65f71 100644 --- a/runtime/lua/vim/lsp/_watchfiles.lua +++ b/runtime/lua/vim/lsp/_watchfiles.lua @@ -1,4 +1,5 @@ local bit = require('bit') +local glob = require('vim.glob') local watch = require('vim._watch') local protocol = require('vim.lsp.protocol') local ms = protocol.Methods @@ -6,88 +7,6 @@ local lpeg = vim.lpeg local M = {} ---- Parses the raw pattern into an |lpeg| pattern. LPeg patterns natively support the "this" or "that" ---- alternative constructions described in the LSP spec that cannot be expressed in a standard Lua pattern. ---- ----@param pattern string The raw glob pattern ----@return vim.lpeg.Pattern? pattern An |lpeg| representation of the pattern, or nil if the pattern is invalid. -local function parse(pattern) - local l = lpeg - - local P, S, V = lpeg.P, lpeg.S, lpeg.V - local C, Cc, Ct, Cf = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cf - - local pathsep = '/' - - local function class(inv, ranges) - for i, r in ipairs(ranges) do - ranges[i] = r[1] .. r[2] - end - local patt = l.R(unpack(ranges)) - if inv == '!' then - patt = P(1) - patt - end - return patt - end - - local function add(acc, a) - return acc + a - end - - local function mul(acc, m) - return acc * m - end - - local function star(stars, after) - return (-after * (l.P(1) - pathsep)) ^ #stars * after - end - - local function dstar(after) - return (-after * l.P(1)) ^ 0 * after - end - - local p = P({ - 'Pattern', - Pattern = V('Elem') ^ -1 * V('End'), - Elem = Cf( - (V('DStar') + V('Star') + V('Ques') + V('Class') + V('CondList') + V('Literal')) - * (V('Elem') + V('End')), - mul - ), - DStar = P('**') * (P(pathsep) * (V('Elem') + V('End')) + V('End')) / dstar, - Star = C(P('*') ^ 1) * (V('Elem') + V('End')) / star, - Ques = P('?') * Cc(l.P(1) - pathsep), - Class = P('[') * C(P('!') ^ -1) * Ct(Ct(C(1) * '-' * C(P(1) - ']')) ^ 1 * ']') / class, - CondList = P('{') * Cf(V('Cond') * (P(',') * V('Cond')) ^ 0, add) * '}', - -- TODO: '*' inside a {} condition is interpreted literally but should probably have the same - -- wildcard semantics it usually has. - -- Fixing this is non-trivial because '*' should match non-greedily up to "the rest of the - -- pattern" which in all other cases is the entire succeeding part of the pattern, but at the end of a {} - -- condition means "everything after the {}" where several other options separated by ',' may - -- exist in between that should not be matched by '*'. - Cond = Cf((V('Ques') + V('Class') + V('CondList') + (V('Literal') - S(',}'))) ^ 1, mul) - + Cc(l.P(0)), - Literal = P(1) / l.P, - End = P(-1) * Cc(l.P(-1)), - }) - - return p:match(pattern) --[[@as vim.lpeg.Pattern?]] -end - ----@private ---- Implementation of LSP 3.17.0's pattern matching: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern ---- ----@param pattern string|vim.lpeg.Pattern The glob pattern (raw or parsed) to match. ----@param s string The string to match against pattern. ----@return boolean Whether or not pattern matches s. -function M._match(pattern, s) - if type(pattern) == 'string' then - local p = assert(parse(pattern)) - return p:match(s) ~= nil - end - return pattern:match(s) ~= nil -end - M._watchfunc = (vim.fn.has('win32') == 1 or vim.fn.has('mac') == 1) and watch.watch or watch.poll ---@type table> client id -> registration id -> cancel function @@ -112,9 +31,9 @@ local to_lsp_change_type = { --- Default excludes the same as VSCode's `files.watcherExclude` setting. --- https://github.com/microsoft/vscode/blob/eef30e7165e19b33daa1e15e92fa34ff4a5df0d3/src/vs/workbench/contrib/files/browser/files.contribution.ts#L261 ---@type vim.lpeg.Pattern parsed Lpeg pattern -M._poll_exclude_pattern = parse('**/.git/{objects,subtree-cache}/**') - + parse('**/node_modules/*/**') - + parse('**/.hg/store/**') +M._poll_exclude_pattern = glob.to_lpeg('**/.git/{objects,subtree-cache}/**') + + glob.to_lpeg('**/node_modules/*/**') + + glob.to_lpeg('**/.hg/store/**') --- Registers the workspace/didChangeWatchedFiles capability dynamically. --- @@ -143,7 +62,7 @@ function M.register(reg, ctx) local glob_pattern = w.globPattern if type(glob_pattern) == 'string' then - local pattern = parse(glob_pattern) + local pattern = glob.to_lpeg(glob_pattern) if not pattern then error('Cannot parse pattern: ' .. glob_pattern) end @@ -155,7 +74,7 @@ function M.register(reg, ctx) local base_uri = glob_pattern.baseUri local uri = type(base_uri) == 'string' and base_uri or base_uri.uri local base_dir = vim.uri_to_fname(uri) - local pattern = parse(glob_pattern.pattern) + local pattern = glob.to_lpeg(glob_pattern.pattern) if not pattern then error('Cannot parse pattern: ' .. glob_pattern.pattern) end -- cgit From 031088fc0afffe4af6fa90d68d5b93ca09992ef1 Mon Sep 17 00:00:00 2001 From: Michal Liszcz Date: Fri, 22 Dec 2023 15:03:13 +0100 Subject: fix(lsp): filetype matching to documentSelector in dynamic capabilities (#25425) Use the get_language_id client option to resolve the filetype when matching the document selector in a dynamic capability. Co-authored-by: Mathias Fussenegger --- runtime/lua/vim/lsp.lua | 2 +- runtime/lua/vim/lsp/_dynamic.lua | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 6476335213..ca7222a8f3 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1073,7 +1073,7 @@ function lsp.start_client(config) end --- @param method string - --- @param opts? {bufnr?: number} + --- @param opts? {bufnr: integer?} client.supports_method = function(method, opts) opts = opts or {} local required_capability = lsp._request_name_to_capability[method] diff --git a/runtime/lua/vim/lsp/_dynamic.lua b/runtime/lua/vim/lsp/_dynamic.lua index 4bee58559f..5edb27b498 100644 --- a/runtime/lua/vim/lsp/_dynamic.lua +++ b/runtime/lua/vim/lsp/_dynamic.lua @@ -55,7 +55,7 @@ function M:unregister(unregisterations) end --- @param method string ---- @param opts? {bufnr?: number} +--- @param opts? {bufnr: integer?} --- @return lsp.Registration? (table|nil) the registration if found --- @private function M:get(method, opts) @@ -69,14 +69,14 @@ function M:get(method, opts) if not documentSelector then return reg end - if M.match(opts.bufnr, documentSelector) then + if self:match(opts.bufnr, documentSelector) then return reg end end end --- @param method string ---- @param opts? {bufnr?: number} +--- @param opts? {bufnr: integer?} --- @private function M:supports(method, opts) return self:get(method, opts) ~= nil @@ -85,13 +85,17 @@ end --- @param bufnr number --- @param documentSelector lsp.DocumentSelector --- @private -function M.match(bufnr, documentSelector) - local ft = vim.bo[bufnr].filetype +function M:match(bufnr, documentSelector) + local client = vim.lsp.get_client_by_id(self.client_id) + if not client then + return false + end + local language = client.config.get_language_id(bufnr, vim.bo[bufnr].filetype) local uri = vim.uri_from_bufnr(bufnr) local fname = vim.uri_to_fname(uri) for _, filter in ipairs(documentSelector) do local matches = true - if filter.language and ft ~= filter.language then + if filter.language and language ~= filter.language then matches = false end if matches and filter.scheme and not vim.startswith(uri, filter.scheme .. ':') then -- cgit From 7fa292c52d7bf63d59730946ef220befe4d51900 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Sat, 23 Dec 2023 19:45:19 +0900 Subject: fix(treesitter): outdated highlight due to tree with outdated region Problem: A region managed by an injected parser may shrink after re-running the injection query. If the updated region goes out of the range to be parsed, then the corresponding tree will remain outdated, possibly retaining the nodes that shouldn't exist anymore. This results in outdated highlights. Solution: Re-parse an invalid tree if its region intersects the range to be parsed. --- runtime/lua/vim/treesitter/languagetree.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 0171b416cd..a249a10f47 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -348,7 +348,13 @@ function LanguageTree:_parse_regions(range) -- If there are no ranges, set to an empty list -- so the included ranges in the parser are cleared. for i, ranges in pairs(self:included_regions()) do - if not self._valid[i] and intercepts_region(ranges, range) then + if + not self._valid[i] + and ( + intercepts_region(ranges, range) + or (self._trees[i] and intercepts_region(self._trees[i]:included_ranges(false), range)) + ) + then self._parser:set_included_ranges(ranges) local parse_time, tree, tree_changes = tcall(self._parser.parse, self._parser, self._trees[i], self._source, true) -- cgit From 2ff2785c396e66c285fecf5b151d8f8863f9d4e6 Mon Sep 17 00:00:00 2001 From: Pablo Arias Date: Mon, 25 Dec 2023 01:30:56 +0100 Subject: feat(health): checkhealth buffer can show in a split window (#26714) :checkhealth now respects :vertical and :horizontal. For example: :vertical checkhealth foo bar will open the healthcheck buffer in a vertical split. --- runtime/lua/vim/health.lua | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua index 6e47a22d03..4659ab1694 100644 --- a/runtime/lua/vim/health.lua +++ b/runtime/lua/vim/health.lua @@ -268,14 +268,27 @@ end -- Runs the specified healthchecks. -- Runs all discovered healthchecks if plugin_names is empty. -function M._check(plugin_names) +-- splitmod controls how the healthcheck window opens: "vertical", "horizontal" or "tab" +function M._check(splitmod, plugin_names) local healthchecks = plugin_names == '' and get_healthcheck('*') or get_healthcheck(plugin_names) - -- Create buffer and open in a tab, unless this is the default buffer when Nvim starts. local emptybuf = vim.fn.bufnr('$') == 1 and vim.fn.getline(1) == '' and 1 == vim.fn.line('$') - local mod = emptybuf and 'buffer' or 'tab sbuffer' + local mod = function() + if splitmod == 'vertical' then + return 'vertical sbuffer' + elseif splitmod == 'horizontal' then + return 'horizontal sbuffer' + elseif emptybuf then + -- if this is the default buffer when Nvim starts, open healthcheck directly + return 'buffer' + else + -- if not specified otherwise open healthcheck in a tab + return 'tab sbuffer' + end + end + local bufnr = vim.api.nvim_create_buf(true, true) - vim.cmd(mod .. ' ' .. bufnr) + vim.cmd(mod() .. ' ' .. bufnr) if vim.fn.bufexists('health://') == 1 then vim.cmd.bwipe('health://') -- cgit From 2877672d70e76f71ae1190090b8aea7044d458be Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 25 Dec 2023 10:21:13 +0800 Subject: feat(health): make :checkhealth support more split modifiers (#26731) --- runtime/lua/vim/health.lua | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua index 4659ab1694..6c96a703bb 100644 --- a/runtime/lua/vim/health.lua +++ b/runtime/lua/vim/health.lua @@ -266,29 +266,22 @@ M._complete = function() return vim.tbl_keys(unique) end --- Runs the specified healthchecks. --- Runs all discovered healthchecks if plugin_names is empty. --- splitmod controls how the healthcheck window opens: "vertical", "horizontal" or "tab" -function M._check(splitmod, plugin_names) +--- Runs the specified healthchecks. +--- Runs all discovered healthchecks if plugin_names is empty. +--- +--- @param mods string command modifiers that affect splitting a window. +function M._check(mods, plugin_names) local healthchecks = plugin_names == '' and get_healthcheck('*') or get_healthcheck(plugin_names) local emptybuf = vim.fn.bufnr('$') == 1 and vim.fn.getline(1) == '' and 1 == vim.fn.line('$') - local mod = function() - if splitmod == 'vertical' then - return 'vertical sbuffer' - elseif splitmod == 'horizontal' then - return 'horizontal sbuffer' - elseif emptybuf then - -- if this is the default buffer when Nvim starts, open healthcheck directly - return 'buffer' - else - -- if not specified otherwise open healthcheck in a tab - return 'tab sbuffer' - end - end + + -- When no command modifiers are used: + -- - If the current buffer is empty, open healthcheck directly. + -- - If not specified otherwise open healthcheck in a tab. + local buf_cmd = #mods > 0 and (mods .. ' sbuffer') or emptybuf and 'buffer' or 'tab sbuffer' local bufnr = vim.api.nvim_create_buf(true, true) - vim.cmd(mod() .. ' ' .. bufnr) + vim.cmd(buf_cmd .. ' ' .. bufnr) if vim.fn.bufexists('health://') == 1 then vim.cmd.bwipe('health://') -- cgit From e8acbc1ade5082563a9464ed3d1225414723390d Mon Sep 17 00:00:00 2001 From: bfredl Date: Fri, 6 Oct 2023 23:01:24 +0200 Subject: refactor(cpoptions): remove 'p' Deleting a cpo flag a day keeps the doctor away We don't need two different ways to indent LISP code --- runtime/lua/vim/_meta/options.lua | 3 --- 1 file changed, 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 209c27cfd8..46497179ac 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -1296,9 +1296,6 @@ vim.bo.ci = vim.bo.copyindent --- when it didn't exist when editing it. This is a --- protection against a file unexpectedly created by --- someone else. Vi didn't complain about this. ---- *cpo-p* ---- p Vi compatible Lisp indenting. When not present, a ---- slightly better algorithm is used. --- *cpo-P* --- P When included, a ":write" command that appends to a --- file will set the file name for the current buffer, if -- cgit From 0a598c13b1863ba1aff378027c4376e3ab7048ee Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 25 Dec 2023 16:31:38 +0100 Subject: feat(vim.deprecate): only issue warning if neovim version is high enough As specified by MAINTAIN.md, features should be soft deprecated at first (meaning no warnings) to give people a chance to adjust. The problem with this approach is that deprecating a feature becomes harder than usual as during the soft deprecation period you need to remember not to issue a warning, and during the hard deprecation period you need to remember to start issuing a warning. This behavior is only enforced if the `plugin` parameter is `nil` as plugins may not want this specific behavior. --- runtime/lua/vim/_editor.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 0bb1becf58..dda89e2bdb 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -1019,6 +1019,18 @@ end --- ---@return string|nil # Deprecated message, or nil if no message was shown. function vim.deprecate(name, alternative, version, plugin, backtrace) + -- Only issue warning if feature is hard-deprecated as specified by MAINTAIN.md. + if plugin == nil then + local current_version = vim.version() + local deprecated_version = assert(vim.version.parse(version)) + local soft_deprecated_version = + { deprecated_version.major, deprecated_version.minor - 1, deprecated_version.patch } + local deprecate = vim.version.lt(current_version, soft_deprecated_version) + if deprecate then + return + end + end + local msg = ('%s is deprecated'):format(name) plugin = plugin or 'Nvim' msg = alternative and ('%s, use %s instead.'):format(msg, alternative) or msg -- cgit From bbd5c6363c25e8fbbfb962f8f6c5ea1800d431ca Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Tue, 26 Dec 2023 00:16:03 +0100 Subject: feat(extmarks): add virt_text_repeat_linebreak flag (#26625) Problem: Unable to predict which byte-offset to place virtual text to make it repeat visually in the wrapped part of a line. Solution: Add a flag to nvim_buf_set_extmark() that causes virtual text to repeat in wrapped lines. --- runtime/lua/vim/_meta/api.lua | 2 ++ runtime/lua/vim/_meta/api_keysets.lua | 1 + 2 files changed, 3 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index c8c3e1c3af..ba18a16488 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -519,6 +519,8 @@ function vim.api.nvim_buf_line_count(buffer) end --- text is selected or hidden because of scrolling with --- 'nowrap' or 'smoothscroll'. Currently only affects --- "overlay" virt_text. +--- • virt_text_repeat_linebreak : repeat the virtual text on +--- wrapped lines. --- • hl_mode : control how highlights are combined with the --- highlights of the text. Currently only affects virt_text --- highlights, but might affect `hl_group` in later versions. diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index 4ec8b03d30..bb1031b2fa 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -251,6 +251,7 @@ error('Cannot require a meta file') --- @field virt_text_pos? string --- @field virt_text_win_col? integer --- @field virt_text_hide? boolean +--- @field virt_text_repeat_linebreak? boolean --- @field hl_eol? boolean --- @field hl_mode? string --- @field invalidate? boolean -- cgit From 5f9d4d8afeb5dc3d5df4965c24cbb4c6e01694f7 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 25 Dec 2023 21:28:28 +0100 Subject: refactor: use vim.deprecate on all deprecated functions --- runtime/lua/vim/_editor.lua | 2 +- runtime/lua/vim/diagnostic.lua | 16 +++++++--------- runtime/lua/vim/lsp.lua | 8 +++++++- runtime/lua/vim/lsp/buf.lua | 2 +- runtime/lua/vim/lsp/util.lua | 11 +++++++---- runtime/lua/vim/treesitter/language.lua | 5 +++++ 6 files changed, 28 insertions(+), 16 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index dda89e2bdb..0b338fa86f 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -888,7 +888,7 @@ end ---@private function vim.pretty_print(...) - vim.deprecate('vim.pretty_print', 'vim.print', '0.10') + vim.deprecate('vim.pretty_print()', 'vim.print()', '0.10') return vim.print(...) end diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 6d2c212dfc..a82a61eeb7 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -891,15 +891,13 @@ M.handlers.signs = { local sign = vim.fn.sign_getdefined(name)[1] if sign then local severity = M.severity[v:upper()] - if vim.fn.has('nvim-0.11') == 1 then - vim.deprecate( - 'Defining diagnostic signs with :sign-define or sign_define()', - 'vim.diagnostic.config()', - '0.12', - nil, - false - ) - end + vim.deprecate( + 'Defining diagnostic signs with :sign-define or sign_define()', + 'vim.diagnostic.config()', + '0.12', + nil, + false + ) if not opts.signs.text then opts.signs.text = {} diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index ca7222a8f3..1310239a5b 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1740,7 +1740,7 @@ end ---@private ---@deprecated function lsp.get_active_clients(filter) - -- TODO: add vim.deprecate call after 0.10 is out for removal in 0.12 + vim.deprecate('vim.lsp.get_active_clients()', 'vim.lsp.get_clients()', '0.12') return lsp.get_clients(filter) end @@ -2051,6 +2051,7 @@ end ---@return table result is table of (client_id, client) pairs ---@deprecated Use |vim.lsp.get_clients()| instead. function lsp.buf_get_clients(bufnr) + vim.deprecate('vim.lsp.buf_get_clients()', 'vim.lsp.get_clients()', '0.12') local result = {} --- @type table for _, client in ipairs(lsp.get_clients({ bufnr = resolve_bufnr(bufnr) })) do result[client.id] = client @@ -2101,6 +2102,11 @@ end --- buffer number as arguments. ---@deprecated use lsp.get_clients({ bufnr = bufnr }) with regular loop function lsp.for_each_buffer_client(bufnr, fn) + vim.deprecate( + 'vim.lsp.for_each_buffer_client()', + 'lsp.get_clients({ bufnr = bufnr }) with regular loop', + '0.12' + ) return for_each_buffer_client(bufnr, fn) end diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 2f754444e9..051b9d4550 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -34,7 +34,7 @@ end ---@return boolean if server responds. ---@deprecated function M.server_ready() - vim.deprecate('vim.lsp.buf.server_ready', nil, '0.10.0') + vim.deprecate('vim.lsp.buf.server_ready()', nil, '0.10') return not not vim.lsp.buf_notify(0, 'window/progress', {}) end diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 63c4c1e7fc..ba7ce3c2b6 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -180,6 +180,7 @@ local _str_byteindex_enc = M._str_byteindex_enc ---@param new_lines (table) list of strings to replace the original ---@return table The modified {lines} object function M.set_lines(lines, A, B, new_lines) + vim.deprecate('vim.lsp.util.set_lines()', 'nil', '0.12') -- 0-indexing to 1-indexing local i_0 = A[1] + 1 -- If it extends past the end, truncate it to the end. This is because the @@ -346,7 +347,7 @@ end ---@private ---@deprecated Use vim.lsp.status() or access client.progress directly function M.get_progress_messages() - vim.deprecate('vim.lsp.util.get_progress_messages', 'vim.lsp.status', '0.11.0') + vim.deprecate('vim.lsp.util.get_progress_messages()', 'vim.lsp.status()', '0.11') local new_messages = {} local progress_remove = {} @@ -552,7 +553,7 @@ end ---@return lsp.CompletionItem[] List of completion items ---@see https://microsoft.github.io/language-server-protocol/specification#textDocument_completion function M.extract_completion_items(result) - vim.deprecate('vim.lsp.util.extract_completion_items', nil, '0.11') + vim.deprecate('vim.lsp.util.extract_completion_items()', nil, '0.11') if type(result) == 'table' and result.items then -- result is a `CompletionList` return result.items @@ -612,7 +613,7 @@ end ---@param input string unparsed snippet ---@return string parsed snippet function M.parse_snippet(input) - vim.deprecate('vim.lsp.util.parse_snippet', nil, '0.11') + vim.deprecate('vim.lsp.util.parse_snippet()', nil, '0.11') local ok, parsed = pcall(function() return snippet.parse(input) end) @@ -634,7 +635,7 @@ end ---@return table[] items ---@see complete-items function M.text_document_completion_list_to_complete_items(result, prefix) - vim.deprecate('vim.lsp.util.text_document_completion_list_to_complete_items', nil, '0.11') + vim.deprecate('vim.lsp.util.text_document_completion_list_to_complete_items()', nil, '0.11') return require('vim.lsp._completion')._lsp_to_complete_items(result, prefix) end @@ -1885,6 +1886,7 @@ end ---@param lines table list of lines to trim ---@return table trimmed list of lines function M.trim_empty_lines(lines) + vim.deprecate('vim.lsp.util.trim_empty_lines()', 'vim.split() with `trimempty`', '0.12') local start = 1 for i = 1, #lines do if lines[i] ~= nil and #lines[i] > 0 then @@ -1911,6 +1913,7 @@ end ---@param lines table list of lines ---@return string filetype or "markdown" if it was unchanged. function M.try_trim_markdown_code_blocks(lines) + vim.deprecate('vim.lsp.util.try_trim_markdown_code_blocks()', 'nil', '0.12') local language_id = lines[1]:match('^```(.*)') if language_id then local has_inner_code_fence = false diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 15bf666a1e..2056c337c8 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -37,6 +37,11 @@ end ---@deprecated function M.require_language(lang, path, silent, symbol_name) + vim.deprecate( + 'vim.treesitter.language.require_language()', + 'vim.treesitter.language.add()', + '0.12' + ) local opts = { silent = silent, path = path, -- cgit From 5cb906e91cb56302d0737aa80e2d890dde452029 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Tue, 26 Dec 2023 15:16:45 +0100 Subject: fix: correct versions in deprecation warnings The following functions should be removed in 0.12 according to the deprecation strategy in MAINTAIN.md: - vim.lsp.util.extract_completion_items() - vim.lsp.util.parse_snippet() - vim.lsp.util.text_document_completion_list_to_complete_items() --- runtime/lua/vim/lsp/util.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index ba7ce3c2b6..90e2f28ef4 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -553,7 +553,7 @@ end ---@return lsp.CompletionItem[] List of completion items ---@see https://microsoft.github.io/language-server-protocol/specification#textDocument_completion function M.extract_completion_items(result) - vim.deprecate('vim.lsp.util.extract_completion_items()', nil, '0.11') + vim.deprecate('vim.lsp.util.extract_completion_items()', nil, '0.12') if type(result) == 'table' and result.items then -- result is a `CompletionList` return result.items @@ -613,7 +613,7 @@ end ---@param input string unparsed snippet ---@return string parsed snippet function M.parse_snippet(input) - vim.deprecate('vim.lsp.util.parse_snippet()', nil, '0.11') + vim.deprecate('vim.lsp.util.parse_snippet()', nil, '0.12') local ok, parsed = pcall(function() return snippet.parse(input) end) @@ -635,7 +635,7 @@ end ---@return table[] items ---@see complete-items function M.text_document_completion_list_to_complete_items(result, prefix) - vim.deprecate('vim.lsp.util.text_document_completion_list_to_complete_items()', nil, '0.11') + vim.deprecate('vim.lsp.util.text_document_completion_list_to_complete_items()', nil, '0.12') return require('vim.lsp._completion')._lsp_to_complete_items(result, prefix) end -- cgit From c26dc1f77c792fe5cbefd578dc8d1e23c80d3688 Mon Sep 17 00:00:00 2001 From: Nacho Nieva <83428506+NachoNievaG@users.noreply.github.com> Date: Tue, 26 Dec 2023 20:26:18 -0300 Subject: feat(defaults): map Q and @x to repeat in Visual mode (#26495) --- runtime/lua/vim/_defaults.lua | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 2627cbcd0d..0d756b8701 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -67,6 +67,21 @@ do --- See |&-default| vim.keymap.set('n', '&', ':&&', { desc = ':help &-default' }) + --- Use Q in visual mode to execute a macro on each line of the selection. #21422 + --- + --- Applies to @x and includes @@ too. + vim.keymap.set( + 'x', + 'Q', + ':normal! @=reg_recorded()', + { silent = true, desc = ':help v_Q-default' } + ) + vim.keymap.set( + 'x', + '@', + "':normal! @'.getcharstr().''", + { silent = true, expr = true, desc = ':help v_@-default' } + ) --- Map |gx| to call |vim.ui.open| on the identifier under the cursor do -- TODO: use vim.region() when it lands... #13896 #16843 -- cgit From 3767468b9615b617e252e9e9498e070087fe570f Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Mon, 11 Dec 2023 00:05:24 -0500 Subject: docs(gen_lsp.lua): re-generate vim.lsp._meta.protocol type annotations The purpose of this commit is to make diff clean and easy to read; to see the diff resulted from actual changes in gen_lsp.lua, not from the updated LSP protocol JSON data. Ran: `nvim -l scripts/gen_lsp.lua gen --methods` Based on 3.18.0 (2023-12-23) --- runtime/lua/vim/lsp/_meta/protocol.lua | 127 ++++++++++++++++++++++++++------- runtime/lua/vim/lsp/protocol.lua | 44 ++++++------ 2 files changed, 122 insertions(+), 49 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/_meta/protocol.lua b/runtime/lua/vim/lsp/_meta/protocol.lua index 979dad84fd..dc7970c1b4 100644 --- a/runtime/lua/vim/lsp/_meta/protocol.lua +++ b/runtime/lua/vim/lsp/_meta/protocol.lua @@ -472,6 +472,9 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@class lsp.InlayHint ---The position of this hint. +--- +---If multiple hints have the same position, they will be shown in the order +---they appear in the response. ---@field position lsp.Position ---The label of this hint. A human readable string or an array of ---InlayHintLabelPart label parts. @@ -614,12 +617,16 @@ error('Cannot require a meta file') ---A parameter literal used in inline completion requests. --- ---@since 3.18.0 +---@proposed ---@class lsp.InlineCompletionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams ---Additional information about the context in which inline completions were ---requested. ---@field context lsp.InlineCompletionContext ---Represents a collection of {@link InlineCompletionItem inline completion items} to be presented in the editor. +--- +---@since 3.18.0 +---@proposed ---@class lsp.InlineCompletionList ---The inline completion items ---@field items lsp.InlineCompletionItem[] @@ -627,11 +634,10 @@ error('Cannot require a meta file') ---An inline completion item represents a text snippet that is proposed inline to complete text that is being typed. --- ---@since 3.18.0 +---@proposed ---@class lsp.InlineCompletionItem ---The text to replace the range with. Must be set. ----@field insertText string ----The format of the insert text. The format applies to the `insertText`. If omitted defaults to `InsertTextFormat.PlainText`. ----@field insertTextFormat? lsp.InsertTextFormat +---@field insertText string|lsp.StringValue ---A text that is used to decide if this inline completion should be shown. When `falsy` the {@link InlineCompletionItem.insertText} is used. ---@field filterText? string ---The range to replace. Must begin and end on the same line. @@ -642,6 +648,7 @@ error('Cannot require a meta file') ---Inline completion options used during static or dynamic registration. --- ---@since 3.18.0 +---@proposed ---@class lsp.InlineCompletionRegistrationOptions: lsp.InlineCompletionOptions, lsp.StaticRegistrationOptions ---@class lsp.RegistrationParams @@ -981,14 +988,23 @@ error('Cannot require a meta file') ---In future version of the protocol this property might become ---mandatory to better express this. ---@field activeSignature? uinteger ----The active parameter of the active signature. If omitted or the value ----lies outside the range of `signatures[activeSignature].parameters` ----defaults to 0 if the active signature has parameters. If ----the active signature has no parameters it is ignored. +---The active parameter of the active signature. +--- +---If `null`, no parameter of the signature is active (for example a named +---argument that does not match any declared parameters). This is only valid +---since 3.18.0 and if the client specifies the client capability +---`textDocument.signatureHelp.noActiveParameterSupport === true` +--- +---If omitted or the value lies outside the range of +---`signatures[activeSignature].parameters` defaults to 0 if the active +---signature has parameters. +--- +---If the active signature has no parameters it is ignored. +--- ---In future version of the protocol this property might become ----mandatory to better express the active parameter if the ----active signature does have any. ----@field activeParameter? uinteger +---mandatory (but still nullable) to better express the active parameter if +---the active signature does have any. +---@field activeParameter? uinteger|lsp.null ---Registration options for a {@link SignatureHelpRequest}. ---@class lsp.SignatureHelpRegistrationOptions: lsp.TextDocumentRegistrationOptions @@ -1192,8 +1208,7 @@ error('Cannot require a meta file') ---The command this code lens represents. ---@field command? lsp.Command ---A data entry field that is preserved on a code lens item between ----a {@link CodeLensRequest} and a [CodeLensResolveRequest] ----(#CodeLensResolveRequest) +---a {@link CodeLensRequest} and a {@link CodeLensResolveRequest} ---@field data? lsp.LSPAny ---Registration options for a {@link CodeLensRequest}. @@ -1470,7 +1485,7 @@ error('Cannot require a meta file') ---@class lsp.ConfigurationItem ---The scope to get the configuration section for. ----@field scopeUri? string +---@field scopeUri? lsp.URI ---The configuration section asked for. ---@field section? string @@ -1503,14 +1518,14 @@ error('Cannot require a meta file') ---offset of b is 3 since `𐐀` is represented using two code units in UTF-16. ---Since 3.17 clients and servers can agree on a different string encoding ---representation (e.g. UTF-8). The client announces it's supported encoding ----via the client capability [`general.positionEncodings`](#clientCapabilities). +---via the client capability [`general.positionEncodings`](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#clientCapabilities). ---The value is an array of position encodings the client supports, with ---decreasing preference (e.g. the encoding at index `0` is the most preferred ---one). To stay backwards compatible the only mandatory encoding is UTF-16 ---represented via the string `utf-16`. The server can pick one of the ---encodings offered by the client and signals that encoding back to the ---client via the initialize result's property ----[`capabilities.positionEncoding`](#serverCapabilities). If the string value +---[`capabilities.positionEncoding`](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#serverCapabilities). If the string value ---`utf-16` is missing from the client's capability `general.positionEncodings` ---servers can safely assume that the client supports UTF-16. If the server ---omits the position encoding in its initialize result the encoding defaults @@ -1915,18 +1930,36 @@ error('Cannot require a meta file') ---Provides information about the context in which an inline completion was requested. --- ---@since 3.18.0 +---@proposed ---@class lsp.InlineCompletionContext ---Describes how the inline completion was triggered. ---@field triggerKind lsp.InlineCompletionTriggerKind ---Provides information about the currently selected item in the autocomplete widget if it is visible. ---@field selectedCompletionInfo? lsp.SelectedCompletionInfo +---A string value used as a snippet is a template which allows to insert text +---and to control the editor cursor when insertion happens. +--- +---A snippet can define tab stops and placeholders with `$1`, `$2` +---and `${3:foo}`. `$0` defines the final tab stop, it defaults to +---the end of the snippet. Variables are defined with `$name` and +---`${name:default value}`. +--- +---@since 3.18.0 +---@proposed +---@class lsp.StringValue +---The kind of string value. +---@field kind "snippet" +---The snippet string. +---@field value string + ---Inline completion options used during static registration. --- ---@since 3.18.0 +---@proposed ---@class lsp.InlineCompletionOptions ----General parameters to to register for an notification or to register a provider. +---General parameters to register for a notification or to register a provider. ---@class lsp.Registration ---The id used to register the request. The id can be used to deregister ---the request again. @@ -2097,6 +2130,7 @@ error('Cannot require a meta file') ---Inline completion options used during static registration. --- ---@since 3.18.0 +---@proposed ---@field inlineCompletionProvider? boolean|lsp.InlineCompletionOptions ---Workspace specific server capabilities. ---@field workspace? anonym12 @@ -2261,10 +2295,16 @@ error('Cannot require a meta file') ---@field parameters? lsp.ParameterInformation[] ---The index of the active parameter. --- ----If provided, this is used in place of `SignatureHelp.activeParameter`. +---If `null`, no parameter of the signature is active (for example a named +---argument that does not match any declared parameters). This is only valid +---since 3.18.0 and if the client specifies the client capability +---`textDocument.signatureHelp.noActiveParameterSupport === true` +--- +---If provided (or `null`), this is used in place of +---`SignatureHelp.activeParameter`. --- ---@since 3.16.0 ----@field activeParameter? uinteger +---@field activeParameter? uinteger|lsp.null ---Server Capabilities for a {@link SignatureHelpRequest}. ---@class lsp.SignatureHelpOptions @@ -2545,6 +2585,7 @@ error('Cannot require a meta file') ---Describes the currently selected completion item. --- ---@since 3.18.0 +---@proposed ---@class lsp.SelectedCompletionInfo ---The range that will be replaced if this completion item is accepted. ---@field range lsp.Range @@ -2758,6 +2799,11 @@ error('Cannot require a meta file') --- ---@since 3.17.0. ---@field diagnostics? lsp.DiagnosticWorkspaceClientCapabilities +---Capabilities specific to the folding range requests scoped to the workspace. +--- +---@since 3.18.0 +---@proposed +---@field foldingRange? lsp.FoldingRangeWorkspaceClientCapabilities ---Text document specific client capabilities. ---@class lsp.TextDocumentClientCapabilities @@ -2853,6 +2899,7 @@ error('Cannot require a meta file') ---Client capabilities specific to inline completions. --- ---@since 3.18.0 +---@proposed ---@field inlineCompletion? lsp.InlineCompletionClientCapabilities ---Capabilities specific to the notebook document support. @@ -3083,6 +3130,23 @@ error('Cannot require a meta file') ---change that requires such a calculation. ---@field refreshSupport? boolean +---Client workspace capabilities specific to folding ranges +--- +---@since 3.18.0 +---@proposed +---@class lsp.FoldingRangeWorkspaceClientCapabilities +---Whether the client implementation supports a refresh request sent from the +---server to the client. +--- +---Note that this event is global and will force the client to refresh all +---folding ranges currently shown. It should be used with absolute care and is +---useful for situation where a server for example detects a project wide +---change that requires such a calculation. +--- +---@since 3.18.0 +---@proposed +---@field refreshSupport? boolean + ---@class lsp.TextDocumentSyncClientCapabilities ---Whether text document synchronization supports dynamic registration. ---@field dynamicRegistration? boolean @@ -3474,6 +3538,7 @@ error('Cannot require a meta file') ---Client capabilities specific to inline completions. --- ---@since 3.18.0 +---@proposed ---@class lsp.InlineCompletionClientCapabilities ---Whether implementation supports dynamic registration for inline completion providers. ---@field dynamicRegistration? boolean @@ -3662,18 +3727,13 @@ error('Cannot require a meta file') ---| 1 # Type ---| 2 # Parameter ----Defines whether the insert text in a completion item should be interpreted as ----plain text or a snippet. ----@alias lsp.InsertTextFormat ----| 1 # PlainText ----| 2 # Snippet - ---The message type ---@alias lsp.MessageType ---| 1 # Error ---| 2 # Warning ---| 3 # Info ---| 4 # Log +---| 5 # Debug ---Defines how the host (editor) should sync ---document changes to the language server. @@ -3723,6 +3783,12 @@ error('Cannot require a meta file') ---@alias lsp.CompletionItemTag ---| 1 # Deprecated +---Defines whether the insert text in a completion item should be interpreted as +---plain text or a snippet. +---@alias lsp.InsertTextFormat +---| 1 # PlainText +---| 2 # Snippet + ---How whitespace and indentation is handled during completion ---item insertion. --- @@ -3766,6 +3832,7 @@ error('Cannot require a meta file') ---Describes how an {@link InlineCompletionItemProvider inline completion provider} was triggered. --- ---@since 3.18.0 +---@proposed ---@alias lsp.InlineCompletionTriggerKind ---| 0 # Invoked ---| 1 # Automatic @@ -4247,6 +4314,12 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@field activeParameterSupport? boolean +---The client supports the `activeParameter` property on +---`SignatureInformation` being set to `null` to indicate that no +---parameter should be active. +--- +---@since 3.18.0 +---@field noActiveParameterSupport? boolean ---@class anonym31 ---The symbol kind values the client supports. When this @@ -4352,7 +4425,7 @@ error('Cannot require a meta file') ---@field language string ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme? string ----A glob pattern, like `*.{ts,js}`. +---A glob pattern, like **​/*.{ts,js}. See TextDocumentFilter for examples. ---@field pattern? string ---@class anonym50 @@ -4360,7 +4433,7 @@ error('Cannot require a meta file') ---@field language? string ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme string ----A glob pattern, like `*.{ts,js}`. +---A glob pattern, like **​/*.{ts,js}. See TextDocumentFilter for examples. ---@field pattern? string ---@class anonym51 @@ -4368,7 +4441,7 @@ error('Cannot require a meta file') ---@field language? string ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme? string ----A glob pattern, like `*.{ts,js}`. +---A glob pattern, like **​/*.{ts,js}. See TextDocumentFilter for examples. ---@field pattern string ---@class anonym52 diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index b2a92cd1ee..df12c36396 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -934,7 +934,7 @@ end -- Generated by gen_lsp.lua, keep at end of file. --- LSP method names. --- ----@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#metaModel +---@see https://microsoft.github.io/language-server-protocol/specification/#metaModel protocol.Methods = { --- A request to resolve the incoming calls for a given `CallHierarchyItem`. --- @since 3.16.0 @@ -1021,16 +1021,14 @@ protocol.Methods = { --- `filterText`, `insertText`, and `textEdit`, must not be changed during resolve. textDocument_completion = 'textDocument/completion', --- A request to resolve the type definition locations of a symbol at a given text - --- document position. The request's parameter is of type [TextDocumentPositionParams] - --- (#TextDocumentPositionParams) the response is of type {@link Declaration} - --- or a typed array of {@link DeclarationLink} or a Thenable that resolves - --- to such. + --- document position. The request's parameter is of type {@link TextDocumentPositionParams} + --- the response is of type {@link Declaration} or a typed array of {@link DeclarationLink} + --- or a Thenable that resolves to such. textDocument_declaration = 'textDocument/declaration', --- A request to resolve the definition location of a symbol at a given text - --- document position. The request's parameter is of type [TextDocumentPosition] - --- (#TextDocumentPosition) the response is of either type {@link Definition} - --- or a typed array of {@link DefinitionLink} or a Thenable that resolves - --- to such. + --- document position. The request's parameter is of type {@link TextDocumentPosition} + --- the response is of either type {@link Definition} or a typed array of + --- {@link DefinitionLink} or a Thenable that resolves to such. textDocument_definition = 'textDocument/definition', --- The document diagnostic request definition. --- @since 3.17.0 @@ -1064,9 +1062,9 @@ protocol.Methods = { --- that resolves to such. textDocument_documentColor = 'textDocument/documentColor', --- Request to resolve a {@link DocumentHighlight} for a given - --- text document position. The request's parameter is of type [TextDocumentPosition] - --- (#TextDocumentPosition) the request response is of type [DocumentHighlight[]] - --- (#DocumentHighlight) or a Thenable that resolves to such. + --- text document position. The request's parameter is of type {@link TextDocumentPosition} + --- the request response is an array of type {@link DocumentHighlight} + --- or a Thenable that resolves to such. textDocument_documentHighlight = 'textDocument/documentHighlight', --- A request to provide document links textDocument_documentLink = 'textDocument/documentLink', @@ -1080,16 +1078,15 @@ protocol.Methods = { --- response is of type {@link FoldingRangeList} or a Thenable --- that resolves to such. textDocument_foldingRange = 'textDocument/foldingRange', - --- A request to to format a whole document. + --- A request to format a whole document. textDocument_formatting = 'textDocument/formatting', --- Request to request hover information at a given text document position. The request's --- parameter is of type {@link TextDocumentPosition} the response is of --- type {@link Hover} or a Thenable that resolves to such. textDocument_hover = 'textDocument/hover', --- A request to resolve the implementation locations of a symbol at a given text - --- document position. The request's parameter is of type [TextDocumentPositionParams] - --- (#TextDocumentPositionParams) the response is of type {@link Definition} or a - --- Thenable that resolves to such. + --- document position. The request's parameter is of type {@link TextDocumentPositionParams} + --- the response is of type {@link Definition} or a Thenable that resolves to such. textDocument_implementation = 'textDocument/implementation', --- A request to provide inlay hints in a document. The request's parameter is of --- type {@link InlayHintsParams}, the response is of type @@ -1100,6 +1097,7 @@ protocol.Methods = { --- type {@link InlineCompletionParams}, the response is of type --- {@link InlineCompletion InlineCompletion[]} or a Thenable that resolves to such. --- @since 3.18.0 + --- @proposed textDocument_inlineCompletion = 'textDocument/inlineCompletion', --- A request to provide inline values in a document. The request's parameter is of --- type {@link InlineValueParams}, the response is of type @@ -1155,9 +1153,8 @@ protocol.Methods = { textDocument_semanticTokens_range = 'textDocument/semanticTokens/range', textDocument_signatureHelp = 'textDocument/signatureHelp', --- A request to resolve the type definition locations of a symbol at a given text - --- document position. The request's parameter is of type [TextDocumentPositionParams] - --- (#TextDocumentPositionParams) the response is of type {@link Definition} or a - --- Thenable that resolves to such. + --- document position. The request's parameter is of type {@link TextDocumentPositionParams} + --- the response is of type {@link Definition} or a Thenable that resolves to such. textDocument_typeDefinition = 'textDocument/typeDefinition', --- A document will save notification is sent from the client to the server before --- the document is actually saved. @@ -1200,14 +1197,14 @@ protocol.Methods = { --- symbol's location. --- @since 3.17.0 workspaceSymbol_resolve = 'workspaceSymbol/resolve', - --- A request sent from the server to the client to modified certain resources. + --- A request sent from the server to the client to modify certain resources. workspace_applyEdit = 'workspace/applyEdit', --- A request to refresh all code actions --- @since 3.16.0 workspace_codeLens_refresh = 'workspace/codeLens/refresh', --- The 'workspace/configuration' request is sent from the server to the client to fetch a certain --- configuration setting. - --- This pull model replaces the old push model were the client signaled configuration change via an + --- This pull model replaces the old push model where the client signaled configuration change via an --- event. If the server still needs to react to configuration changes (since the server caches the --- result of `workspace/configuration` requests) the server should register for an empty configuration --- change event and empty the cache if such an event is received. @@ -1240,9 +1237,12 @@ protocol.Methods = { --- files were renamed from within the client. --- @since 3.16.0 workspace_didRenameFiles = 'workspace/didRenameFiles', - --- A request send from the client to the server to execute a command. The request might return + --- A request sent from the client to the server to execute a command. The request might return --- a workspace edit which the client will apply to the workspace. workspace_executeCommand = 'workspace/executeCommand', + --- @since 3.18.0 + --- @proposed + workspace_foldingRange_refresh = 'workspace/foldingRange/refresh', --- @since 3.17.0 workspace_inlayHint_refresh = 'workspace/inlayHint/refresh', --- @since 3.17.0 -- cgit From 6c35fb421e888d0cbdfac07a5ff4579c9be7f0ec Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Mon, 11 Dec 2023 02:25:17 -0500 Subject: fix(gen_lsp.lua): improve type name, and fix wrong type inheritance Style improvements: 1. Anonymous classes derived from `StructureLiteralType` should have a better name. The class name can be also nested. Examples: ```diff ----@field serverInfo? anonym1 +---@field serverInfo? lsp._anonym1.serverInfo ``` ```diff ----@field insertTextModeSupport? anonym26 +---@field insertTextModeSupport? lsp._anonym26.completionItem.insertTextModeSupport ``` 2. Add one separate empty line before each `@field` definition. Without these, empty lines the doc can look confusing because descriptions also may contain empty lines. See `lsp.CompletionItem` for example: ```lua ---The kind of this completion item. Based of the kind ---an icon is chosen by the editor. ---@field kind? lsp.CompletionItemKind ---Tags for this completion item. --- ---@since 3.15.0 ---@field tags? lsp.CompletionItemTag[] ``` It might feel like "Tags for this completion item" belongs to `kind`, not `tags` due to the lack of separator blank lines. The following (after this commit) should look much better: ```diff ---The kind of this completion item. Based of the kind ---an icon is chosen by the editor. ---@field kind? lsp.CompletionItemKind +--- ---Tags for this completion item. --- ---@since 3.15.0 ---@field tags? lsp.CompletionItemTag[] ``` 3. Escape some LSP-specific annotations that can't be recognized by lua-ls. It'd be better to make them visible in LSP hover doc windows. Example: `@sample ...`. Fixes: 1. A type may extend from more than one base types (as well as mixin types). Previously only the first base class was being considered, resulting incomplete base classes for `@class` definitions. Example: `InlayHintOptions` (should have both of `resolveProvider` and `workDoneProgress`, the latter is from `WorkDoneProgressOptions`) ```diff ----@class lsp.InlayHintOptions +---@class lsp.InlayHintOptions: lsp.WorkDoneProgressOptions ``` 2. Remove `<200b>` (zero-width space) unicode characters. 3. Add the missing newline at EOF. --- runtime/lua/vim/lsp/_meta/protocol.lua | 1182 ++++++++++++++++++++++++++------ 1 file changed, 985 insertions(+), 197 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/_meta/protocol.lua b/runtime/lua/vim/lsp/_meta/protocol.lua index dc7970c1b4..4c053cb57e 100644 --- a/runtime/lua/vim/lsp/_meta/protocol.lua +++ b/runtime/lua/vim/lsp/_meta/protocol.lua @@ -21,99 +21,123 @@ error('Cannot require a meta file') ---Represents a location inside a resource, such as a line ---inside a text file. ---@class lsp.Location +--- ---@field uri lsp.DocumentUri +--- ---@field range lsp.Range ----@class lsp.ImplementationRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.ImplementationRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.ImplementationOptions, lsp.StaticRegistrationOptions ---@class lsp.TypeDefinitionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams ----@class lsp.TypeDefinitionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.TypeDefinitionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.TypeDefinitionOptions, lsp.StaticRegistrationOptions ---A workspace folder inside a client. ---@class lsp.WorkspaceFolder +--- ---The associated URI for this workspace folder. ---@field uri lsp.URI +--- ---The name of the workspace folder. Used to refer to this ---workspace folder in the user interface. ---@field name string ---The parameters of a `workspace/didChangeWorkspaceFolders` notification. ---@class lsp.DidChangeWorkspaceFoldersParams +--- ---The actual workspace folder change event. ---@field event lsp.WorkspaceFoldersChangeEvent ---The parameters of a configuration request. ---@class lsp.ConfigurationParams +--- ---@field items lsp.ConfigurationItem[] ---Parameters for a {@link DocumentColorRequest}. ----@class lsp.DocumentColorParams +---@class lsp.DocumentColorParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier ---Represents a color range from a document. ---@class lsp.ColorInformation +--- ---The range in the document where this color appears. ---@field range lsp.Range +--- ---The actual color value for this color range. ---@field color lsp.Color ----@class lsp.DocumentColorRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.DocumentColorRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentColorOptions, lsp.StaticRegistrationOptions ---Parameters for a {@link ColorPresentationRequest}. ----@class lsp.ColorPresentationParams +---@class lsp.ColorPresentationParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The color to request presentations for. ---@field color lsp.Color +--- ---The range where the color would be inserted. Serves as a context. ---@field range lsp.Range ---@class lsp.ColorPresentation +--- ---The label of this color presentation. It will be shown on the color ---picker header. By default this is also the text that is inserted when selecting ---this color presentation. ---@field label string +--- ---An {@link TextEdit edit} which is applied to a document when selecting ---this presentation for the color. When `falsy` the {@link ColorPresentation.label label} ---is used. ---@field textEdit? lsp.TextEdit +--- ---An optional array of additional {@link TextEdit text edits} that are applied when ---selecting this color presentation. Edits must not overlap with the main {@link ColorPresentation.textEdit edit} nor with themselves. ---@field additionalTextEdits? lsp.TextEdit[] ---@class lsp.WorkDoneProgressOptions +--- ---@field workDoneProgress? boolean ---General text document registration options. ---@class lsp.TextDocumentRegistrationOptions +--- ---A document selector to identify the scope of the registration. If set to null ---the document selector provided on the client side will be used. ---@field documentSelector lsp.DocumentSelector|lsp.null ---Parameters for a {@link FoldingRangeRequest}. ----@class lsp.FoldingRangeParams +---@class lsp.FoldingRangeParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier ---Represents a folding range. To be valid, start and end line must be bigger than zero and smaller ---than the number of lines in the document. Clients are free to ignore invalid ranges. ---@class lsp.FoldingRange +--- ---The zero-based start line of the range to fold. The folded area starts after the line's last character. ---To be valid, the end must be zero or larger and smaller than the number of lines in the document. ---@field startLine uinteger +--- ---The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line. ---@field startCharacter? uinteger +--- ---The zero-based end line of the range to fold. The folded area ends with the line's last character. ---To be valid, the end must be zero or larger and smaller than the number of lines in the document. ---@field endLine uinteger +--- ---The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line. ---@field endCharacter? uinteger +--- ---Describes the kind of the folding range such as `comment' or 'region'. The kind ---is used to categorize folding ranges and used by commands like 'Fold all comments'. ---See {@link FoldingRangeKind} for an enumeration of standardized kinds. ---@field kind? lsp.FoldingRangeKind +--- ---The text that the client should show when the specified range is ---collapsed. If not defined or not supported by the client, a default ---will be chosen by the client. @@ -121,34 +145,40 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@field collapsedText? string ----@class lsp.FoldingRangeRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.FoldingRangeRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.FoldingRangeOptions, lsp.StaticRegistrationOptions ---@class lsp.DeclarationParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams ----@class lsp.DeclarationRegistrationOptions: lsp.DeclarationOptions, lsp.StaticRegistrationOptions +---@class lsp.DeclarationRegistrationOptions: lsp.DeclarationOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions ---A parameter literal used in selection range requests. ----@class lsp.SelectionRangeParams +---@class lsp.SelectionRangeParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The positions inside the text document. ---@field positions lsp.Position[] ---A selection range represents a part of a selection hierarchy. A selection range ---may have a parent selection range that contains it. ---@class lsp.SelectionRange +--- ---The {@link Range range} of this selection range. ---@field range lsp.Range +--- ---The parent selection range containing this range. Therefore `parent.range` must contain `this.range`. ---@field parent? lsp.SelectionRange ----@class lsp.SelectionRangeRegistrationOptions: lsp.SelectionRangeOptions, lsp.StaticRegistrationOptions +---@class lsp.SelectionRangeRegistrationOptions: lsp.SelectionRangeOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions ---@class lsp.WorkDoneProgressCreateParams +--- ---The token to be used to report progress. ---@field token lsp.ProgressToken ---@class lsp.WorkDoneProgressCancelParams +--- ---The token to be used to report progress. ---@field token lsp.ProgressToken @@ -162,21 +192,29 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.CallHierarchyItem +--- ---The name of this item. ---@field name string +--- ---The kind of this item. ---@field kind lsp.SymbolKind +--- ---Tags for this item. ---@field tags? lsp.SymbolTag[] +--- ---More detail for this item, e.g. the signature of a function. ---@field detail? string +--- ---The resource identifier of this item. ---@field uri lsp.DocumentUri +--- ---The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code. ---@field range lsp.Range +--- ---The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function. ---Must be contained by the {@link CallHierarchyItem.range `range`}. ---@field selectionRange lsp.Range +--- ---A data entry field that is preserved between a call hierarchy prepare and ---incoming calls or outgoing calls requests. ---@field data? lsp.LSPAny @@ -184,20 +222,23 @@ error('Cannot require a meta file') ---Call hierarchy options used during static or dynamic registration. --- ---@since 3.16.0 ----@class lsp.CallHierarchyRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.CallHierarchyRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.CallHierarchyOptions, lsp.StaticRegistrationOptions ---The parameter of a `callHierarchy/incomingCalls` request. --- ---@since 3.16.0 ----@class lsp.CallHierarchyIncomingCallsParams +---@class lsp.CallHierarchyIncomingCallsParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---@field item lsp.CallHierarchyItem ---Represents an incoming call, e.g. a caller of a method or constructor. --- ---@since 3.16.0 ---@class lsp.CallHierarchyIncomingCall +--- ---The item that makes the call. ---@field from lsp.CallHierarchyItem +--- ---The ranges at which the calls appear. This is relative to the caller ---denoted by {@link CallHierarchyIncomingCall.from `this.from`}. ---@field fromRanges lsp.Range[] @@ -205,64 +246,78 @@ error('Cannot require a meta file') ---The parameter of a `callHierarchy/outgoingCalls` request. --- ---@since 3.16.0 ----@class lsp.CallHierarchyOutgoingCallsParams +---@class lsp.CallHierarchyOutgoingCallsParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---@field item lsp.CallHierarchyItem ---Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc. --- ---@since 3.16.0 ---@class lsp.CallHierarchyOutgoingCall +--- ---The item that is called. ---@field to lsp.CallHierarchyItem +--- ---The range at which this item is called. This is the range relative to the caller, e.g the item ---passed to {@link CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls `provideCallHierarchyOutgoingCalls`} ---and not {@link CallHierarchyOutgoingCall.to `this.to`}. ---@field fromRanges lsp.Range[] ---@since 3.16.0 ----@class lsp.SemanticTokensParams +---@class lsp.SemanticTokensParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier ---@since 3.16.0 ---@class lsp.SemanticTokens +--- ---An optional result id. If provided and clients support delta updating ---the client will include the result id in the next semantic token request. ---A server can then instead of computing all semantic tokens again simply ---send a delta. ---@field resultId? string +--- ---The actual tokens. ---@field data uinteger[] ---@since 3.16.0 ---@class lsp.SemanticTokensPartialResult +--- ---@field data uinteger[] ---@since 3.16.0 ----@class lsp.SemanticTokensRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.SemanticTokensRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.SemanticTokensOptions, lsp.StaticRegistrationOptions ---@since 3.16.0 ----@class lsp.SemanticTokensDeltaParams +---@class lsp.SemanticTokensDeltaParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The result id of a previous response. The result Id can either point to a full response ---or a delta response depending on what was received last. ---@field previousResultId string ---@since 3.16.0 ---@class lsp.SemanticTokensDelta +--- ---@field resultId? string +--- ---The semantic token edits to transform a previous result into a new result. ---@field edits lsp.SemanticTokensEdit[] ---@since 3.16.0 ---@class lsp.SemanticTokensDeltaPartialResult +--- ---@field edits lsp.SemanticTokensEdit[] ---@since 3.16.0 ----@class lsp.SemanticTokensRangeParams +---@class lsp.SemanticTokensRangeParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The range the semantic tokens are requested for. ---@field range lsp.Range @@ -270,17 +325,21 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.ShowDocumentParams +--- ---The uri to show. ---@field uri lsp.URI +--- ---Indicates to show the resource in an external program. ---To show, for example, `https://code.visualstudio.com/` ---in the default WEB browser set `external` to `true`. ---@field external? boolean +--- ---An optional property to indicate whether the editor ---showing the document should take focus or not. ---Clients might ignore this property if an external ---program is started. ---@field takeFocus? boolean +--- ---An optional selection range if the document is a text ---document. Clients might ignore the property if an ---external program is started or the file is not a text @@ -291,6 +350,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.ShowDocumentResult +--- ---A boolean indicating if the show was successful. ---@field success boolean @@ -300,21 +360,24 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.LinkedEditingRanges +--- ---A list of ranges that can be edited together. The ranges must have ---identical length and contain identical text content. The ranges cannot overlap. ---@field ranges lsp.Range[] +--- ---An optional word pattern (regular expression) that describes valid contents for ---the given ranges. If no pattern is provided, the client configuration's word ---pattern will be used. ---@field wordPattern? string ----@class lsp.LinkedEditingRangeRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.LinkedEditingRangeRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.LinkedEditingRangeOptions, lsp.StaticRegistrationOptions ---The parameters sent in notifications/requests for user-initiated creation of ---files. --- ---@since 3.16.0 ---@class lsp.CreateFilesParams +--- ---An array of all files/folders created in this operation. ---@field files lsp.FileCreate[] @@ -331,8 +394,10 @@ error('Cannot require a meta file') ---cause failure of the operation. How the client recovers from the failure is described by ---the client capability: `workspace.workspaceEdit.failureHandling` ---@class lsp.WorkspaceEdit +--- ---Holds changes to existing resources. ---@field changes? table +--- ---Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes ---are either an array of `TextDocumentEdit`s to express changes to n different text documents ---where each text document edit addresses a specific version of a text document. Or it can contain @@ -344,6 +409,7 @@ error('Cannot require a meta file') ---If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then ---only plain `TextEdit`s using the `changes` property are supported. ---@field documentChanges? lsp.TextDocumentEdit|lsp.CreateFile|lsp.RenameFile|lsp.DeleteFile[] +--- ---A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and ---delete file / folder operations. --- @@ -356,6 +422,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileOperationRegistrationOptions +--- ---The actual filters. ---@field filters lsp.FileOperationFilter[] @@ -364,6 +431,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.RenameFilesParams +--- ---An array of all files/folders renamed in this operation. When a folder is renamed, only ---the folder will be included, and not its children. ---@field files lsp.FileRename[] @@ -373,6 +441,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.DeleteFilesParams +--- ---An array of all files/folders deleted in this operation. ---@field files lsp.FileDelete[] @@ -382,17 +451,21 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.Moniker +--- ---The scheme of the moniker. For example tsc or .Net ---@field scheme string +--- ---The identifier of the moniker. The value is opaque in LSIF however ---schema owners are allowed to define the structure if they want. ---@field identifier string +--- ---The scope in which the moniker is unique ---@field unique lsp.UniquenessLevel +--- ---The moniker kind if known. ---@field kind? lsp.MonikerKind ----@class lsp.MonikerRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.MonikerRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.MonikerOptions ---The parameter of a `textDocument/prepareTypeHierarchy` request. --- @@ -401,23 +474,31 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@class lsp.TypeHierarchyItem +--- ---The name of this item. ---@field name string +--- ---The kind of this item. ---@field kind lsp.SymbolKind +--- ---Tags for this item. ---@field tags? lsp.SymbolTag[] +--- ---More detail for this item, e.g. the signature of a function. ---@field detail? string +--- ---The resource identifier of this item. ---@field uri lsp.DocumentUri +--- ---The range enclosing this symbol not including leading/trailing whitespace ---but everything else, e.g. comments and code. ---@field range lsp.Range +--- ---The range that should be selected and revealed when this symbol is being ---picked, e.g. the name of a function. Must be contained by the ---{@link TypeHierarchyItem.range `range`}. ---@field selectionRange lsp.Range +--- ---A data entry field that is preserved between a type hierarchy prepare and ---supertypes or subtypes requests. It could also be used to identify the ---type hierarchy in the server, helping improve the performance on @@ -427,28 +508,33 @@ error('Cannot require a meta file') ---Type hierarchy options used during static or dynamic registration. --- ---@since 3.17.0 ----@class lsp.TypeHierarchyRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.TypeHierarchyRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.TypeHierarchyOptions, lsp.StaticRegistrationOptions ---The parameter of a `typeHierarchy/supertypes` request. --- ---@since 3.17.0 ----@class lsp.TypeHierarchySupertypesParams +---@class lsp.TypeHierarchySupertypesParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---@field item lsp.TypeHierarchyItem ---The parameter of a `typeHierarchy/subtypes` request. --- ---@since 3.17.0 ----@class lsp.TypeHierarchySubtypesParams +---@class lsp.TypeHierarchySubtypesParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---@field item lsp.TypeHierarchyItem ---A parameter literal used in inline value requests. --- ---@since 3.17.0 ----@class lsp.InlineValueParams +---@class lsp.InlineValueParams: lsp.WorkDoneProgressParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The document range for which inline values should be computed. ---@field range lsp.Range +--- ---Additional information about the context in which inline values were ---requested. ---@field context lsp.InlineValueContext @@ -456,14 +542,16 @@ error('Cannot require a meta file') ---Inline value options used during static or dynamic registration. --- ---@since 3.17.0 ----@class lsp.InlineValueRegistrationOptions: lsp.InlineValueOptions, lsp.StaticRegistrationOptions +---@class lsp.InlineValueRegistrationOptions: lsp.InlineValueOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions ---A parameter literal used in inlay hint requests. --- ---@since 3.17.0 ----@class lsp.InlayHintParams +---@class lsp.InlayHintParams: lsp.WorkDoneProgressParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The document range for which inlay hints should be computed. ---@field range lsp.Range @@ -471,39 +559,47 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlayHint +--- ---The position of this hint. --- ---If multiple hints have the same position, they will be shown in the order ---they appear in the response. ---@field position lsp.Position +--- ---The label of this hint. A human readable string or an array of ---InlayHintLabelPart label parts. --- ---*Note* that neither the string nor the label part can be empty. ---@field label string|lsp.InlayHintLabelPart[] +--- ---The kind of this hint. Can be omitted in which case the client ---should fall back to a reasonable default. ---@field kind? lsp.InlayHintKind +--- ---Optional text edits that are performed when accepting this inlay hint. --- ---*Note* that edits are expected to change the document so that the inlay ---hint (or its nearest variant) is now part of the document and the inlay ---hint itself is now obsolete. ---@field textEdits? lsp.TextEdit[] +--- ---The tooltip text when you hover over this item. ---@field tooltip? string|lsp.MarkupContent +--- ---Render padding before the hint. --- ---Note: Padding should use the editor's background color, not the ---background color of the hint itself. That means padding can be used ---to visually align/separate an inlay hint. ---@field paddingLeft? boolean +--- ---Render padding after the hint. --- ---Note: Padding should use the editor's background color, not the ---background color of the hint itself. That means padding can be used ---to visually align/separate an inlay hint. ---@field paddingRight? boolean +--- ---A data entry field that is preserved on an inlay hint between ---a `textDocument/inlayHint` and a `inlayHint/resolve` request. ---@field data? lsp.LSPAny @@ -511,16 +607,19 @@ error('Cannot require a meta file') ---Inlay hint options used during static or dynamic registration. --- ---@since 3.17.0 ----@class lsp.InlayHintRegistrationOptions: lsp.InlayHintOptions, lsp.StaticRegistrationOptions +---@class lsp.InlayHintRegistrationOptions: lsp.InlayHintOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions ---Parameters of the document diagnostic request. --- ---@since 3.17.0 ----@class lsp.DocumentDiagnosticParams +---@class lsp.DocumentDiagnosticParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The additional identifier provided during registration. ---@field identifier? string +--- ---The result id of a previous response if provided. ---@field previousResultId? string @@ -528,25 +627,29 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.DocumentDiagnosticReportPartialResult +--- ---@field relatedDocuments table ---Cancellation data returned from a diagnostic request. --- ---@since 3.17.0 ---@class lsp.DiagnosticServerCancellationData +--- ---@field retriggerRequest boolean ---Diagnostic registration options. --- ---@since 3.17.0 ----@class lsp.DiagnosticRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.DiagnosticRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DiagnosticOptions, lsp.StaticRegistrationOptions ---Parameters of the workspace diagnostic request. --- ---@since 3.17.0 ----@class lsp.WorkspaceDiagnosticParams +---@class lsp.WorkspaceDiagnosticParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The additional identifier provided during registration. ---@field identifier? string +--- ---The currently known diagnostic reports with their ---previous result ids. ---@field previousResultIds lsp.PreviousResultId[] @@ -555,20 +658,24 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.WorkspaceDiagnosticReport +--- ---@field items lsp.WorkspaceDocumentDiagnosticReport[] ---A partial result for a workspace diagnostic report. --- ---@since 3.17.0 ---@class lsp.WorkspaceDiagnosticReportPartialResult +--- ---@field items lsp.WorkspaceDocumentDiagnosticReport[] ---The params sent in an open notebook document notification. --- ---@since 3.17.0 ---@class lsp.DidOpenNotebookDocumentParams +--- ---The notebook document that got opened. ---@field notebookDocument lsp.NotebookDocument +--- ---The text documents that represent the content ---of a notebook cell. ---@field cellTextDocuments lsp.TextDocumentItem[] @@ -577,11 +684,13 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.DidChangeNotebookDocumentParams +--- ---The notebook document that did change. The version number points ---to the version after all provided changes have been applied. If ---only the text document content of a cell changes the notebook version ---doesn't necessarily have to change. ---@field notebookDocument lsp.VersionedNotebookDocumentIdentifier +--- ---The actual changes to the notebook document. --- ---The changes describe single state changes to the notebook document. @@ -601,6 +710,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.DidSaveNotebookDocumentParams +--- ---The notebook document that got saved. ---@field notebookDocument lsp.NotebookDocumentIdentifier @@ -608,8 +718,10 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.DidCloseNotebookDocumentParams +--- ---The notebook document that got closed. ---@field notebookDocument lsp.NotebookDocumentIdentifier +--- ---The text documents that represent the content ---of a notebook cell that got closed. ---@field cellTextDocuments lsp.TextDocumentIdentifier[] @@ -619,6 +731,7 @@ error('Cannot require a meta file') ---@since 3.18.0 ---@proposed ---@class lsp.InlineCompletionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams +--- ---Additional information about the context in which inline completions were ---requested. ---@field context lsp.InlineCompletionContext @@ -628,6 +741,7 @@ error('Cannot require a meta file') ---@since 3.18.0 ---@proposed ---@class lsp.InlineCompletionList +--- ---The inline completion items ---@field items lsp.InlineCompletionItem[] @@ -636,12 +750,16 @@ error('Cannot require a meta file') ---@since 3.18.0 ---@proposed ---@class lsp.InlineCompletionItem +--- ---The text to replace the range with. Must be set. ---@field insertText string|lsp.StringValue +--- ---A text that is used to decide if this inline completion should be shown. When `falsy` the {@link InlineCompletionItem.insertText} is used. ---@field filterText? string +--- ---The range to replace. Must begin and end on the same line. ---@field range? lsp.Range +--- ---An optional {@link Command} that is executed *after* inserting this completion. ---@field command? lsp.Command @@ -649,28 +767,33 @@ error('Cannot require a meta file') --- ---@since 3.18.0 ---@proposed ----@class lsp.InlineCompletionRegistrationOptions: lsp.InlineCompletionOptions, lsp.StaticRegistrationOptions +---@class lsp.InlineCompletionRegistrationOptions: lsp.InlineCompletionOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions ---@class lsp.RegistrationParams +--- ---@field registrations lsp.Registration[] ---@class lsp.UnregistrationParams +--- ---@field unregisterations lsp.Unregistration[] ----@class lsp.InitializeParams: lsp._InitializeParams +---@class lsp.InitializeParams: lsp._InitializeParams, lsp.WorkspaceFoldersInitializeParams ---The result returned from an initialize request. ---@class lsp.InitializeResult +--- ---The capabilities the language server provides. ---@field capabilities lsp.ServerCapabilities +--- ---Information about the server. --- ---@since 3.15.0 ----@field serverInfo? anonym1 +---@field serverInfo? lsp._anonym1.serverInfo ---The data type of the ResponseError if the ---initialize request fails. ---@class lsp.InitializeError +--- ---Indicates whether the client execute the following retry logic: ---(1) show the message provided by the ResponseError to the user ---(2) user selects retry or cancel @@ -681,49 +804,62 @@ error('Cannot require a meta file') ---The parameters of a change configuration notification. ---@class lsp.DidChangeConfigurationParams +--- ---The actual changed settings ---@field settings lsp.LSPAny ---@class lsp.DidChangeConfigurationRegistrationOptions +--- ---@field section? string|string[] ---The parameters of a notification message. ---@class lsp.ShowMessageParams +--- ---The message type. See {@link MessageType} ---@field type lsp.MessageType +--- ---The actual message. ---@field message string ---@class lsp.ShowMessageRequestParams +--- ---The message type. See {@link MessageType} ---@field type lsp.MessageType +--- ---The actual message. ---@field message string +--- ---The message action items to present. ---@field actions? lsp.MessageActionItem[] ---@class lsp.MessageActionItem +--- ---A short title like 'Retry', 'Open Log' etc. ---@field title string ---The log message parameters. ---@class lsp.LogMessageParams +--- ---The message type. See {@link MessageType} ---@field type lsp.MessageType +--- ---The actual message. ---@field message string ---The parameters sent in an open text document notification ---@class lsp.DidOpenTextDocumentParams +--- ---The document that was opened. ---@field textDocument lsp.TextDocumentItem ---The change text document notification's parameters. ---@class lsp.DidChangeTextDocumentParams +--- ---The document that did change. The version number points ---to the version after all provided content changes have ---been applied. ---@field textDocument lsp.VersionedTextDocumentIdentifier +--- ---The actual content changes. The content changes describe single state changes ---to the document. So if there are two content changes c1 (at array index 0) and ---c2 (at array index 1) for a document in state S then c1 moves the document from @@ -739,64 +875,78 @@ error('Cannot require a meta file') ---Describe options to be used when registered for text document change events. ---@class lsp.TextDocumentChangeRegistrationOptions: lsp.TextDocumentRegistrationOptions +--- ---How documents are synced to the server. ---@field syncKind lsp.TextDocumentSyncKind ---The parameters sent in a close text document notification ---@class lsp.DidCloseTextDocumentParams +--- ---The document that was closed. ---@field textDocument lsp.TextDocumentIdentifier ---The parameters sent in a save text document notification ---@class lsp.DidSaveTextDocumentParams +--- ---The document that was saved. ---@field textDocument lsp.TextDocumentIdentifier +--- ---Optional the content when saved. Depends on the includeText value ---when the save notification was requested. ---@field text? string ---Save registration options. ----@class lsp.TextDocumentSaveRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.TextDocumentSaveRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.SaveOptions ---The parameters sent in a will save text document notification. ---@class lsp.WillSaveTextDocumentParams +--- ---The document that will be saved. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The 'TextDocumentSaveReason'. ---@field reason lsp.TextDocumentSaveReason ---A text edit applicable to a text document. ---@class lsp.TextEdit +--- ---The range of the text document to be manipulated. To insert ---text into a document create a range where start === end. ---@field range lsp.Range +--- ---The string to be inserted. For delete operations use an ---empty string. ---@field newText string ---The watched files change notification's parameters. ---@class lsp.DidChangeWatchedFilesParams +--- ---The actual file events. ---@field changes lsp.FileEvent[] ---Describe options to be used when registered for text document change events. ---@class lsp.DidChangeWatchedFilesRegistrationOptions +--- ---The watchers to register. ---@field watchers lsp.FileSystemWatcher[] ---The publish diagnostic notification's parameters. ---@class lsp.PublishDiagnosticsParams +--- ---The URI for which diagnostic information is reported. ---@field uri lsp.DocumentUri +--- ---Optional the version number of the document the diagnostics are published for. --- ---@since 3.15.0 ---@field version? integer +--- ---An array of diagnostic information items. ---@field diagnostics lsp.Diagnostic[] ---Completion parameters ---@class lsp.CompletionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The completion context. This is only available it the client specifies ---to send this using the client capability `textDocument.completion.contextSupport === true` ---@field context? lsp.CompletionContext @@ -804,6 +954,7 @@ error('Cannot require a meta file') ---A completion item represents a text snippet that is ---proposed to complete text that is being typed. ---@class lsp.CompletionItem +--- ---The label of this completion item. --- ---The label property is also by default the text that @@ -812,39 +963,49 @@ error('Cannot require a meta file') ---If label details are provided the label itself should ---be an unqualified name of the completion item. ---@field label string +--- ---Additional details for the label --- ---@since 3.17.0 ---@field labelDetails? lsp.CompletionItemLabelDetails +--- ---The kind of this completion item. Based of the kind ---an icon is chosen by the editor. ---@field kind? lsp.CompletionItemKind +--- ---Tags for this completion item. --- ---@since 3.15.0 ---@field tags? lsp.CompletionItemTag[] +--- ---A human-readable string with additional information ---about this item, like type or symbol information. ---@field detail? string +--- ---A human-readable string that represents a doc-comment. ---@field documentation? string|lsp.MarkupContent +--- ---Indicates if this item is deprecated. ---@deprecated Use `tags` instead. ---@field deprecated? boolean +--- ---Select this item when showing. --- ---*Note* that only one completion item can be selected and that the ---tool / client decides which item that is. The rule is that the *first* ---item of those that match best is selected. ---@field preselect? boolean +--- ---A string that should be used when comparing this item ---with other items. When `falsy` the {@link CompletionItem.label label} ---is used. ---@field sortText? string +--- ---A string that should be used when filtering a set of ---completion items. When `falsy` the {@link CompletionItem.label label} ---is used. ---@field filterText? string +--- ---A string that should be inserted into a document when selecting ---this completion. When `falsy` the {@link CompletionItem.label label} ---is used. @@ -857,6 +1018,7 @@ error('Cannot require a meta file') ---recommended to use `textEdit` instead since it avoids additional client ---side interpretation. ---@field insertText? string +--- ---The format of the insert text. The format applies to both the ---`insertText` property and the `newText` property of a provided ---`textEdit`. If omitted defaults to `InsertTextFormat.PlainText`. @@ -864,12 +1026,14 @@ error('Cannot require a meta file') ---Please note that the insertTextFormat doesn't apply to ---`additionalTextEdits`. ---@field insertTextFormat? lsp.InsertTextFormat +--- ---How whitespace and indentation is handled during completion ---item insertion. If not provided the clients default value depends on ---the `textDocument.completion.insertTextMode` client capability. --- ---@since 3.16.0 ---@field insertTextMode? lsp.InsertTextMode +--- ---An {@link TextEdit edit} which is applied to a document when selecting ---this completion. When an edit is provided the value of ---{@link CompletionItem.insertText insertText} is ignored. @@ -891,6 +1055,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 additional type `InsertReplaceEdit` ---@field textEdit? lsp.TextEdit|lsp.InsertReplaceEdit +--- ---The edit text used if the completion item is part of a CompletionList and ---CompletionList defines an item default for the text edit range. --- @@ -902,6 +1067,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@field textEditText? string +--- ---An optional array of additional {@link TextEdit text edits} that are applied when ---selecting this completion. Edits must not overlap (including the same insert position) ---with the main {@link CompletionItem.textEdit edit} nor with themselves. @@ -910,14 +1076,17 @@ error('Cannot require a meta file') ---(for example adding an import statement at the top of the file if the completion item will ---insert an unqualified type). ---@field additionalTextEdits? lsp.TextEdit[] +--- ---An optional set of characters that when pressed while this completion is active will accept it first and ---then type that character. *Note* that all commit characters should have `length=1` and that superfluous ---characters will be ignored. ---@field commitCharacters? string[] +--- ---An optional {@link Command command} that is executed *after* inserting this completion. *Note* that ---additional modifications to the current document should be described with the ---{@link CompletionItem.additionalTextEdits additionalTextEdits}-property. ---@field command? lsp.Command +--- ---A data entry field that is preserved on a completion item between a ---{@link CompletionRequest} and a {@link CompletionResolveRequest}. ---@field data? lsp.LSPAny @@ -925,11 +1094,13 @@ error('Cannot require a meta file') ---Represents a collection of {@link CompletionItem completion items} to be presented ---in the editor. ---@class lsp.CompletionList +--- ---This list it not complete. Further typing results in recomputing this list. --- ---Recomputed lists have all their items replaced (not appended) in the ---incomplete completion sessions. ---@field isIncomplete boolean +--- ---In many cases the items of an actual completion result share the same ---value for properties like `commitCharacters` or the range of a text ---edit. A completion list can therefore define item defaults which will @@ -943,29 +1114,33 @@ error('Cannot require a meta file') ---capability. --- ---@since 3.17.0 ----@field itemDefaults? anonym3 +---@field itemDefaults? lsp._anonym2.itemDefaults +--- ---The completion items. ---@field items lsp.CompletionItem[] ---Registration options for a {@link CompletionRequest}. ----@class lsp.CompletionRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.CompletionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.CompletionOptions ---Parameters for a {@link HoverRequest}. ---@class lsp.HoverParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams ---The result of a hover request. ---@class lsp.Hover +--- ---The hover's content ---@field contents lsp.MarkupContent|lsp.MarkedString|lsp.MarkedString[] +--- ---An optional range inside the text document that is used to ---visualize the hover, e.g. by changing the background color. ---@field range? lsp.Range ---Registration options for a {@link HoverRequest}. ----@class lsp.HoverRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.HoverRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.HoverOptions ---Parameters for a {@link SignatureHelpRequest}. ---@class lsp.SignatureHelpParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams +--- ---The signature help context. This is only available if the client specifies ---to send this using the client capability `textDocument.signatureHelp.contextSupport === true` --- @@ -976,8 +1151,10 @@ error('Cannot require a meta file') ---callable. There can be multiple signature but only one ---active and only one active parameter. ---@class lsp.SignatureHelp +--- ---One or more signatures. ---@field signatures lsp.SignatureInformation[] +--- ---The active signature. If omitted or the value lies outside the ---range of `signatures` the value defaults to zero or is ignored if ---the `SignatureHelp` has no signatures. @@ -988,6 +1165,7 @@ error('Cannot require a meta file') ---In future version of the protocol this property might become ---mandatory to better express this. ---@field activeSignature? uinteger +--- ---The active parameter of the active signature. --- ---If `null`, no parameter of the signature is active (for example a named @@ -1007,20 +1185,21 @@ error('Cannot require a meta file') ---@field activeParameter? uinteger|lsp.null ---Registration options for a {@link SignatureHelpRequest}. ----@class lsp.SignatureHelpRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.SignatureHelpRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.SignatureHelpOptions ---Parameters for a {@link DefinitionRequest}. ---@class lsp.DefinitionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams ---Registration options for a {@link DefinitionRequest}. ----@class lsp.DefinitionRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DefinitionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DefinitionOptions ---Parameters for a {@link ReferencesRequest}. ---@class lsp.ReferenceParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---@field context lsp.ReferenceContext ---Registration options for a {@link ReferencesRequest}. ----@class lsp.ReferenceRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.ReferenceRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.ReferenceOptions ---Parameters for a {@link DocumentHighlightRequest}. ---@class lsp.DocumentHighlightParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams @@ -1029,26 +1208,31 @@ error('Cannot require a meta file') ---special attention. Usually a document highlight is visualized by changing ---the background color of its range. ---@class lsp.DocumentHighlight +--- ---The range this highlight applies to. ---@field range lsp.Range +--- ---The highlight kind, default is {@link DocumentHighlightKind.Text text}. ---@field kind? lsp.DocumentHighlightKind ---Registration options for a {@link DocumentHighlightRequest}. ----@class lsp.DocumentHighlightRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DocumentHighlightRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentHighlightOptions ---Parameters for a {@link DocumentSymbolRequest}. ----@class lsp.DocumentSymbolParams +---@class lsp.DocumentSymbolParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier ---Represents information about programming constructs like variables, classes, ---interfaces etc. ---@class lsp.SymbolInformation: lsp.BaseSymbolInformation +--- ---Indicates if this symbol is deprecated. --- ---@deprecated Use tags instead ---@field deprecated? boolean +--- ---The location of this symbol. The location's range is used by a tool ---to reveal the location in the editor. If the symbol is selected in the ---tool the range's start information is used to position the cursor. So @@ -1065,40 +1249,51 @@ error('Cannot require a meta file') ---have two ranges: one that encloses its definition and one that points to ---its most interesting range, e.g. the range of an identifier. ---@class lsp.DocumentSymbol +--- ---The name of this symbol. Will be displayed in the user interface and therefore must not be ---an empty string or a string only consisting of white spaces. ---@field name string +--- ---More detail for this symbol, e.g the signature of a function. ---@field detail? string +--- ---The kind of this symbol. ---@field kind lsp.SymbolKind +--- ---Tags for this document symbol. --- ---@since 3.16.0 ---@field tags? lsp.SymbolTag[] +--- ---Indicates if this symbol is deprecated. --- ---@deprecated Use tags instead ---@field deprecated? boolean +--- ---The range enclosing this symbol not including leading/trailing whitespace but everything else ---like comments. This information is typically used to determine if the clients cursor is ---inside the symbol to reveal in the symbol in the UI. ---@field range lsp.Range +--- ---The range that should be selected and revealed when this symbol is being picked, e.g the name of a function. ---Must be contained by the `range`. ---@field selectionRange lsp.Range +--- ---Children of this symbol, e.g. properties of a class. ---@field children? lsp.DocumentSymbol[] ---Registration options for a {@link DocumentSymbolRequest}. ----@class lsp.DocumentSymbolRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DocumentSymbolRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentSymbolOptions ---The parameters of a {@link CodeActionRequest}. ----@class lsp.CodeActionParams +---@class lsp.CodeActionParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The document in which the command was invoked. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The range for which the command was invoked. ---@field range lsp.Range +--- ---Context carrying additional information. ---@field context lsp.CodeActionContext @@ -1107,10 +1302,13 @@ error('Cannot require a meta file') ---an array of arguments which will be passed to the command handler ---function when invoked. ---@class lsp.Command +--- ---Title of the command, like `save`. ---@field title string +--- ---The identifier of the actual command handler. ---@field command string +--- ---Arguments that the command handler should be ---invoked with. ---@field arguments? lsp.LSPAny[] @@ -1120,14 +1318,18 @@ error('Cannot require a meta file') --- ---A CodeAction must set either `edit` and/or a `command`. If both are supplied, the `edit` is applied first, then the `command` is executed. ---@class lsp.CodeAction +--- ---A short, human-readable, title for this code action. ---@field title string +--- ---The kind of the code action. --- ---Used to filter code actions. ---@field kind? lsp.CodeActionKind +--- ---The diagnostics that this code action resolves. ---@field diagnostics? lsp.Diagnostic[] +--- ---Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted ---by keybindings. --- @@ -1136,6 +1338,7 @@ error('Cannot require a meta file') --- ---@since 3.15.0 ---@field isPreferred? boolean +--- ---Marks that the code action cannot currently be applied. --- ---Clients should follow the following guidelines regarding disabled code actions: @@ -1151,13 +1354,16 @@ error('Cannot require a meta file') --- error message with `reason` in the editor. --- ---@since 3.16.0 ----@field disabled? anonym4 +---@field disabled? lsp._anonym4.disabled +--- ---The workspace edit this code action performs. ---@field edit? lsp.WorkspaceEdit +--- ---A command this code action executes. If a code action ---provides an edit and a command, first the edit is ---executed and then the command. ---@field command? lsp.Command +--- ---A data entry field that is preserved on a code action between ---a `textDocument/codeAction` and a `codeAction/resolve` request. --- @@ -1165,10 +1371,11 @@ error('Cannot require a meta file') ---@field data? lsp.LSPAny ---Registration options for a {@link CodeActionRequest}. ----@class lsp.CodeActionRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.CodeActionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.CodeActionOptions ---The parameters of a {@link WorkspaceSymbolRequest}. ----@class lsp.WorkspaceSymbolParams +---@class lsp.WorkspaceSymbolParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---A query string to filter symbols by. Clients may send an empty ---string here to request all symbols. ---@field query string @@ -1179,12 +1386,14 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.WorkspaceSymbol: lsp.BaseSymbolInformation +--- ---The location of the symbol. Whether a server is allowed to ---return a location without a range depends on the client ---capability `workspace.symbol.resolveSupport`. --- ---See SymbolInformation#location for more details. ----@field location lsp.Location|anonym5 +---@field location lsp.Location|lsp._anonym5.location +--- ---A data entry field that is preserved on a workspace symbol between a ---workspace symbol request and a workspace symbol resolve request. ---@field data? lsp.LSPAny @@ -1193,7 +1402,8 @@ error('Cannot require a meta file') ---@class lsp.WorkspaceSymbolRegistrationOptions: lsp.WorkspaceSymbolOptions ---The parameters of a {@link CodeLensRequest}. ----@class lsp.CodeLensParams +---@class lsp.CodeLensParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The document to request code lens for. ---@field textDocument lsp.TextDocumentIdentifier @@ -1203,29 +1413,36 @@ error('Cannot require a meta file') ---A code lens is _unresolved_ when no command is associated to it. For performance ---reasons the creation of a code lens and resolving should be done in two stages. ---@class lsp.CodeLens +--- ---The range in which this code lens is valid. Should only span a single line. ---@field range lsp.Range +--- ---The command this code lens represents. ---@field command? lsp.Command +--- ---A data entry field that is preserved on a code lens item between ---a {@link CodeLensRequest} and a {@link CodeLensResolveRequest} ---@field data? lsp.LSPAny ---Registration options for a {@link CodeLensRequest}. ----@class lsp.CodeLensRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.CodeLensRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.CodeLensOptions ---The parameters of a {@link DocumentLinkRequest}. ----@class lsp.DocumentLinkParams +---@class lsp.DocumentLinkParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The document to provide document links for. ---@field textDocument lsp.TextDocumentIdentifier ---A document link is a range in a text document that links to an internal or external resource, like another ---text document or a web site. ---@class lsp.DocumentLink +--- ---The range this link applies to. ---@field range lsp.Range +--- ---The uri this link points to. If missing a resolve request is sent later. ---@field target? lsp.URI +--- ---The tooltip text when you hover over this link. --- ---If a tooltip is provided, is will be displayed in a string that includes instructions on how to @@ -1234,86 +1451,104 @@ error('Cannot require a meta file') --- ---@since 3.15.0 ---@field tooltip? string +--- ---A data entry field that is preserved on a document link between a ---DocumentLinkRequest and a DocumentLinkResolveRequest. ---@field data? lsp.LSPAny ---Registration options for a {@link DocumentLinkRequest}. ----@class lsp.DocumentLinkRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DocumentLinkRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentLinkOptions ---The parameters of a {@link DocumentFormattingRequest}. ----@class lsp.DocumentFormattingParams +---@class lsp.DocumentFormattingParams: lsp.WorkDoneProgressParams +--- ---The document to format. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The format options. ---@field options lsp.FormattingOptions ---Registration options for a {@link DocumentFormattingRequest}. ----@class lsp.DocumentFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DocumentFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentFormattingOptions ---The parameters of a {@link DocumentRangeFormattingRequest}. ----@class lsp.DocumentRangeFormattingParams +---@class lsp.DocumentRangeFormattingParams: lsp.WorkDoneProgressParams +--- ---The document to format. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The range to format ---@field range lsp.Range +--- ---The format options ---@field options lsp.FormattingOptions ---Registration options for a {@link DocumentRangeFormattingRequest}. ----@class lsp.DocumentRangeFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DocumentRangeFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentRangeFormattingOptions ---The parameters of a {@link DocumentRangesFormattingRequest}. --- ---@since 3.18.0 ---@proposed ----@class lsp.DocumentRangesFormattingParams +---@class lsp.DocumentRangesFormattingParams: lsp.WorkDoneProgressParams +--- ---The document to format. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The ranges to format ---@field ranges lsp.Range[] +--- ---The format options ---@field options lsp.FormattingOptions ---The parameters of a {@link DocumentOnTypeFormattingRequest}. ---@class lsp.DocumentOnTypeFormattingParams +--- ---The document to format. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The position around which the on type formatting should happen. ---This is not necessarily the exact position where the character denoted ---by the property `ch` got typed. ---@field position lsp.Position +--- ---The character that has been typed that triggered the formatting ---on type request. That is not necessarily the last character that ---got inserted into the document since the client could auto insert ---characters as well (e.g. like automatic brace completion). ---@field ch string +--- ---The formatting options. ---@field options lsp.FormattingOptions ---Registration options for a {@link DocumentOnTypeFormattingRequest}. ----@class lsp.DocumentOnTypeFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DocumentOnTypeFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentOnTypeFormattingOptions ---The parameters of a {@link RenameRequest}. ----@class lsp.RenameParams +---@class lsp.RenameParams: lsp.WorkDoneProgressParams +--- ---The document to rename. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The position at which this request was sent. ---@field position lsp.Position +--- ---The new name of the symbol. If the given name is not valid the ---request must return a {@link ResponseError} with an ---appropriate message set. ---@field newName string ---Registration options for a {@link RenameRequest}. ----@class lsp.RenameRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.RenameRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.RenameOptions ---@class lsp.PrepareRenameParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams ---The parameters of a {@link ExecuteCommandRequest}. ----@class lsp.ExecuteCommandParams +---@class lsp.ExecuteCommandParams: lsp.WorkDoneProgressParams +--- ---The identifier of the actual command handler. ---@field command string +--- ---Arguments that the command should be invoked with. ---@field arguments? lsp.LSPAny[] @@ -1322,10 +1557,12 @@ error('Cannot require a meta file') ---The parameters passed via an apply workspace edit request. ---@class lsp.ApplyWorkspaceEditParams +--- ---An optional label of the workspace edit. This label is ---presented in the user interface for example on an undo ---stack to undo the workspace edit. ---@field label? string +--- ---The edits to apply. ---@field edit lsp.WorkspaceEdit @@ -1333,34 +1570,42 @@ error('Cannot require a meta file') --- ---@since 3.17 renamed from ApplyWorkspaceEditResponse ---@class lsp.ApplyWorkspaceEditResult +--- ---Indicates whether the edit was applied or not. ---@field applied boolean +--- ---An optional textual description for why the edit was not applied. ---This may be used by the server for diagnostic logging or to provide ---a suitable error for a request that triggered the edit. ---@field failureReason? string +--- ---Depending on the client's failure handling strategy `failedChange` might ---contain the index of the change that failed. This property is only available ---if the client signals a `failureHandlingStrategy` in its client capabilities. ---@field failedChange? uinteger ---@class lsp.WorkDoneProgressBegin +--- ---@field kind "begin" +--- ---Mandatory title of the progress operation. Used to briefly inform about ---the kind of operation being performed. --- ---Examples: "Indexing" or "Linking dependencies". ---@field title string +--- ---Controls if a cancel button should show to allow the user to cancel the ---long running operation. Clients that don't support cancellation are allowed ---to ignore the setting. ---@field cancellable? boolean +--- ---Optional, more detailed associated progress message. Contains ---complementary information to the `title`. --- ---Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". ---If unset, the previous progress message (if any) is still valid. ---@field message? string +--- ---Optional progress percentage to display (value 100 is considered 100%). ---If not provided infinite progress is assumed and clients are allowed ---to ignore the `percentage` value in subsequent in report notifications. @@ -1370,18 +1615,22 @@ error('Cannot require a meta file') ---@field percentage? uinteger ---@class lsp.WorkDoneProgressReport +--- ---@field kind "report" +--- ---Controls enablement state of a cancel button. --- ---Clients that don't support cancellation or don't support controlling the button's ---enablement state are allowed to ignore the property. ---@field cancellable? boolean +--- ---Optional, more detailed associated progress message. Contains ---complementary information to the `title`. --- ---Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". ---If unset, the previous progress message (if any) is still valid. ---@field message? string +--- ---Optional progress percentage to display (value 100 is considered 100%). ---If not provided infinite progress is assumed and clients are allowed ---to ignore the `percentage` value in subsequent in report notifications. @@ -1391,41 +1640,53 @@ error('Cannot require a meta file') ---@field percentage? uinteger ---@class lsp.WorkDoneProgressEnd +--- ---@field kind "end" +--- ---Optional, a final message indicating to for example indicate the outcome ---of the operation. ---@field message? string ---@class lsp.SetTraceParams +--- ---@field value lsp.TraceValues ---@class lsp.LogTraceParams +--- ---@field message string +--- ---@field verbose? string ---@class lsp.CancelParams +--- ---The request id to cancel. ---@field id integer|string ---@class lsp.ProgressParams +--- ---The progress token provided by the client or server. ---@field token lsp.ProgressToken +--- ---The progress data. ---@field value lsp.LSPAny ---A parameter literal used in requests to pass a text document and a position inside that ---document. ---@class lsp.TextDocumentPositionParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The position inside the text document. ---@field position lsp.Position ---@class lsp.WorkDoneProgressParams +--- ---An optional token that a server can use to report work done progress. ---@field workDoneToken? lsp.ProgressToken ---@class lsp.PartialResultParams +--- ---An optional token that a server can use to report partial results (e.g. streaming) to ---the client. ---@field partialResultToken? lsp.ProgressToken @@ -1433,17 +1694,21 @@ error('Cannot require a meta file') ---Represents the connection of two locations. Provides additional metadata over normal {@link Location locations}, ---including an origin range. ---@class lsp.LocationLink +--- ---Span of the origin of this link. --- ---Used as the underlined span for mouse interaction. Defaults to the word range at ---the definition position. ---@field originSelectionRange? lsp.Range +--- ---The target resource identifier of this link. ---@field targetUri lsp.DocumentUri +--- ---The full target range of this link. If the target for example is a symbol then target range is the ---range enclosing this symbol not including leading/trailing whitespace but everything else ---like comments. This information is typically used to highlight the range in the editor. ---@field targetRange lsp.Range +--- ---The range that should be selected and revealed when this link is being followed, e.g the name of a function. ---Must be contained by the `targetRange`. See also `DocumentSymbol#range` ---@field targetSelectionRange lsp.Range @@ -1460,56 +1725,68 @@ error('Cannot require a meta file') ---} ---``` ---@class lsp.Range +--- ---The range's start position. ---@field start lsp.Position +--- ---The range's end position. ---@field end lsp.Position ----@class lsp.ImplementationOptions +---@class lsp.ImplementationOptions: lsp.WorkDoneProgressOptions ---Static registration options to be returned in the initialize ---request. ---@class lsp.StaticRegistrationOptions +--- ---The id used to register the request. The id can be used to deregister ---the request again. See also Registration#id. ---@field id? string ----@class lsp.TypeDefinitionOptions +---@class lsp.TypeDefinitionOptions: lsp.WorkDoneProgressOptions ---The workspace folder change event. ---@class lsp.WorkspaceFoldersChangeEvent +--- ---The array of added workspace folders ---@field added lsp.WorkspaceFolder[] +--- ---The array of the removed workspace folders ---@field removed lsp.WorkspaceFolder[] ---@class lsp.ConfigurationItem +--- ---The scope to get the configuration section for. ---@field scopeUri? lsp.URI +--- ---The configuration section asked for. ---@field section? string ---A literal to identify a text document in the client. ---@class lsp.TextDocumentIdentifier +--- ---The text document's uri. ---@field uri lsp.DocumentUri ---Represents a color in RGBA space. ---@class lsp.Color +--- ---The red component of this color in the range [0-1]. ---@field red decimal +--- ---The green component of this color in the range [0-1]. ---@field green decimal +--- ---The blue component of this color in the range [0-1]. ---@field blue decimal +--- ---The alpha component of this color in the range [0-1]. ---@field alpha decimal ----@class lsp.DocumentColorOptions +---@class lsp.DocumentColorOptions: lsp.WorkDoneProgressOptions ----@class lsp.FoldingRangeOptions +---@class lsp.FoldingRangeOptions: lsp.WorkDoneProgressOptions ----@class lsp.DeclarationOptions +---@class lsp.DeclarationOptions: lsp.WorkDoneProgressOptions ---Position in a text document expressed as zero-based line and character ---offset. Prior to 3.17 the offsets were always based on a UTF-16 string @@ -1539,11 +1816,13 @@ error('Cannot require a meta file') --- ---@since 3.17.0 - support for negotiated position encoding. ---@class lsp.Position +--- ---Line position in a document (zero-based). --- ---If a line number is greater than the number of lines in a document, it defaults back to the number of lines in the document. ---If a line number is negative, it defaults to 0. ---@field line uinteger +--- ---Character offset on a line in a document (zero-based). --- ---The meaning of this offset is determined by the negotiated @@ -1553,38 +1832,45 @@ error('Cannot require a meta file') ---line length. ---@field character uinteger ----@class lsp.SelectionRangeOptions +---@class lsp.SelectionRangeOptions: lsp.WorkDoneProgressOptions ---Call hierarchy options used during static registration. --- ---@since 3.16.0 ----@class lsp.CallHierarchyOptions +---@class lsp.CallHierarchyOptions: lsp.WorkDoneProgressOptions ---@since 3.16.0 ----@class lsp.SemanticTokensOptions +---@class lsp.SemanticTokensOptions: lsp.WorkDoneProgressOptions +--- ---The legend used by the server ---@field legend lsp.SemanticTokensLegend +--- ---Server supports providing semantic tokens for a specific range ---of a document. ----@field range? boolean|anonym6 +---@field range? boolean|lsp._anonym6.range +--- ---Server supports providing semantic tokens for a full document. ----@field full? boolean|anonym7 +---@field full? boolean|lsp._anonym7.full ---@since 3.16.0 ---@class lsp.SemanticTokensEdit +--- ---The start offset of the edit. ---@field start uinteger +--- ---The count of elements to remove. ---@field deleteCount uinteger +--- ---The elements to insert. ---@field data? uinteger[] ----@class lsp.LinkedEditingRangeOptions +---@class lsp.LinkedEditingRangeOptions: lsp.WorkDoneProgressOptions ---Represents information on a file/folder create. --- ---@since 3.16.0 ---@class lsp.FileCreate +--- ---A file:// URI for the location of the file/folder being created. ---@field uri string @@ -1593,8 +1879,10 @@ error('Cannot require a meta file') ---So the creator of a TextDocumentEdit doesn't need to sort the array of edits or do any ---kind of ordering. However the edits must be non overlapping. ---@class lsp.TextDocumentEdit +--- ---The text document to change. ---@field textDocument lsp.OptionalVersionedTextDocumentIdentifier +--- ---The edits to be applied. --- ---@since 3.16.0 - support for AnnotatedTextEdit. This is guarded using a @@ -1603,30 +1891,40 @@ error('Cannot require a meta file') ---Create file operation. ---@class lsp.CreateFile: lsp.ResourceOperation +--- ---A create ---@field kind "create" +--- ---The resource to create. ---@field uri lsp.DocumentUri +--- ---Additional options ---@field options? lsp.CreateFileOptions ---Rename file operation ---@class lsp.RenameFile: lsp.ResourceOperation +--- ---A rename ---@field kind "rename" +--- ---The old (existing) location. ---@field oldUri lsp.DocumentUri +--- ---The new location. ---@field newUri lsp.DocumentUri +--- ---Rename options. ---@field options? lsp.RenameFileOptions ---Delete file operation ---@class lsp.DeleteFile: lsp.ResourceOperation +--- ---A delete ---@field kind "delete" +--- ---The file to delete. ---@field uri lsp.DocumentUri +--- ---Delete options. ---@field options? lsp.DeleteFileOptions @@ -1634,12 +1932,15 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.ChangeAnnotation +--- ---A human-readable string describing the actual change. The string ---is rendered prominent in the user interface. ---@field label string +--- ---A flag which indicates that user confirmation is needed ---before applying the change. ---@field needsConfirmation? boolean +--- ---A human-readable string which is rendered less prominent in ---the user interface. ---@field description? string @@ -1649,8 +1950,10 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileOperationFilter +--- ---A Uri scheme like `file` or `untitled`. ---@field scheme? string +--- ---The actual file operation pattern. ---@field pattern lsp.FileOperationPattern @@ -1658,8 +1961,10 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileRename +--- ---A file:// URI for the original location of the file/folder being renamed. ---@field oldUri string +--- ---A file:// URI for the new location of the file/folder being renamed. ---@field newUri string @@ -1667,20 +1972,23 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileDelete +--- ---A file:// URI for the location of the file/folder being deleted. ---@field uri string ----@class lsp.MonikerOptions +---@class lsp.MonikerOptions: lsp.WorkDoneProgressOptions ---Type hierarchy options used during static registration. --- ---@since 3.17.0 ----@class lsp.TypeHierarchyOptions +---@class lsp.TypeHierarchyOptions: lsp.WorkDoneProgressOptions ---@since 3.17.0 ---@class lsp.InlineValueContext +--- ---The stack frame (as a DAP Id) where the execution has stopped. ---@field frameId integer +--- ---The document range where execution has stopped. ---Typically the end position of the range denotes the line where the inline values are shown. ---@field stoppedLocation lsp.Range @@ -1689,8 +1997,10 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlineValueText +--- ---The document range for which the inline value applies. ---@field range lsp.Range +--- ---The text of the inline value. ---@field text string @@ -1700,11 +2010,14 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlineValueVariableLookup +--- ---The document range for which the inline value applies. ---The range is used to extract the variable name from the underlying document. ---@field range lsp.Range +--- ---If specified the name of the variable to look up. ---@field variableName? string +--- ---How to perform the lookup. ---@field caseSensitiveLookup boolean @@ -1714,28 +2027,33 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlineValueEvaluatableExpression +--- ---The document range for which the inline value applies. ---The range is used to extract the evaluatable expression from the underlying document. ---@field range lsp.Range +--- ---If specified the expression overrides the extracted expression. ---@field expression? string ---Inline value options used during static registration. --- ---@since 3.17.0 ----@class lsp.InlineValueOptions +---@class lsp.InlineValueOptions: lsp.WorkDoneProgressOptions ---An inlay hint label part allows for interactive and composite labels ---of inlay hints. --- ---@since 3.17.0 ---@class lsp.InlayHintLabelPart +--- ---The value of this label part. ---@field value string +--- ---The tooltip text when you hover over this label part. Depending on ---the client capability `inlayHint.resolveSupport` clients might resolve ---this property late using the resolve request. ---@field tooltip? string|lsp.MarkupContent +--- ---An optional source code location that represents this ---label part. --- @@ -1748,6 +2066,7 @@ error('Cannot require a meta file') ---Depending on the client capability `inlayHint.resolveSupport` clients ---might resolve this property late using the resolve request. ---@field location? lsp.Location +--- ---An optional command for this label part. --- ---Depending on the client capability `inlayHint.resolveSupport` clients @@ -1777,15 +2096,18 @@ error('Cannot require a meta file') ---*Please Note* that clients might sanitize the return markdown. A client could decide to ---remove HTML from the markdown to avoid script execution. ---@class lsp.MarkupContent +--- ---The type of the Markup ---@field kind lsp.MarkupKind +--- ---The content itself ---@field value string ---Inlay hint options used during static registration. --- ---@since 3.17.0 ----@class lsp.InlayHintOptions +---@class lsp.InlayHintOptions: lsp.WorkDoneProgressOptions +--- ---The server provides support to resolve additional ---information for an inlay hint item. ---@field resolveProvider? boolean @@ -1794,6 +2116,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.RelatedFullDocumentDiagnosticReport: lsp.FullDocumentDiagnosticReport +--- ---Diagnostics of related documents. This information is useful ---in programming languages where code in a file A can generate ---diagnostics in a file B which A depends on. An example of @@ -1807,6 +2130,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.RelatedUnchangedDocumentDiagnosticReport: lsp.UnchangedDocumentDiagnosticReport +--- ---Diagnostics of related documents. This information is useful ---in programming languages where code in a file A can generate ---diagnostics in a file B which A depends on. An example of @@ -1820,12 +2144,15 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.FullDocumentDiagnosticReport +--- ---A full document diagnostic report. ---@field kind "full" +--- ---An optional result id. If provided it will ---be sent on the next diagnostic request for the ---same document. ---@field resultId? string +--- ---The actual items. ---@field items lsp.Diagnostic[] @@ -1834,11 +2161,13 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.UnchangedDocumentDiagnosticReport +--- ---A document diagnostic report indicating ---no changes to the last result. A server can ---only return `unchanged` if result ids are ---provided. ---@field kind "unchanged" +--- ---A result id which will be sent on the next ---diagnostic request for the same document. ---@field resultId string @@ -1846,15 +2175,18 @@ error('Cannot require a meta file') ---Diagnostic options. --- ---@since 3.17.0 ----@class lsp.DiagnosticOptions +---@class lsp.DiagnosticOptions: lsp.WorkDoneProgressOptions +--- ---An optional identifier under which the diagnostics are ---managed by the client. ---@field identifier? string +--- ---Whether the language has inter file dependencies meaning that ---editing code in one file can result in a different diagnostic ---set in another file. Inter file dependencies are common for ---most programming languages and typically uncommon for linters. ---@field interFileDependencies boolean +--- ---The server provides support for workspace diagnostics as well. ---@field workspaceDiagnostics boolean @@ -1862,9 +2194,11 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.PreviousResultId +--- ---The URI for which the client knowns a ---result id. ---@field uri lsp.DocumentUri +--- ---The value of the previous result id. ---@field value string @@ -1872,31 +2206,40 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookDocument +--- ---The notebook document's uri. ---@field uri lsp.URI +--- ---The type of the notebook. ---@field notebookType string +--- ---The version number of this document (it will increase after each ---change, including undo/redo). ---@field version integer +--- ---Additional metadata stored with the notebook ---document. --- ---Note: should always be an object literal (e.g. LSPObject) ---@field metadata? lsp.LSPObject +--- ---The cells of a notebook. ---@field cells lsp.NotebookCell[] ---An item to transfer a text document from the client to the ---server. ---@class lsp.TextDocumentItem +--- ---The text document's uri. ---@field uri lsp.DocumentUri +--- ---The text document's language identifier. ---@field languageId string +--- ---The version number of this document (it will increase after each ---change, including undo/redo). ---@field version integer +--- ---The content of the opened text document. ---@field text string @@ -1904,8 +2247,10 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.VersionedNotebookDocumentIdentifier +--- ---The version number of this notebook document. ---@field version integer +--- ---The notebook document's uri. ---@field uri lsp.URI @@ -1913,17 +2258,20 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookDocumentChangeEvent +--- ---The changed meta data if any. --- ---Note: should always be an object literal (e.g. LSPObject) ---@field metadata? lsp.LSPObject +--- ---Changes to cells ----@field cells? anonym10 +---@field cells? lsp._anonym8.cells ---A literal to identify a notebook document in the client. --- ---@since 3.17.0 ---@class lsp.NotebookDocumentIdentifier +--- ---The notebook document's uri. ---@field uri lsp.URI @@ -1932,8 +2280,10 @@ error('Cannot require a meta file') ---@since 3.18.0 ---@proposed ---@class lsp.InlineCompletionContext +--- ---Describes how the inline completion was triggered. ---@field triggerKind lsp.InlineCompletionTriggerKind +--- ---Provides information about the currently selected item in the autocomplete widget if it is visible. ---@field selectedCompletionInfo? lsp.SelectedCompletionInfo @@ -1948,8 +2298,10 @@ error('Cannot require a meta file') ---@since 3.18.0 ---@proposed ---@class lsp.StringValue +--- ---The kind of string value. ---@field kind "snippet" +--- ---The snippet string. ---@field value string @@ -1957,38 +2309,46 @@ error('Cannot require a meta file') --- ---@since 3.18.0 ---@proposed ----@class lsp.InlineCompletionOptions +---@class lsp.InlineCompletionOptions: lsp.WorkDoneProgressOptions ---General parameters to register for a notification or to register a provider. ---@class lsp.Registration +--- ---The id used to register the request. The id can be used to deregister ---the request again. ---@field id string +--- ---The method / capability to register for. ---@field method string +--- ---Options necessary for the registration. ---@field registerOptions? lsp.LSPAny ---General parameters to unregister a request or notification. ---@class lsp.Unregistration +--- ---The id used to unregister the request or notification. Usually an id ---provided during the register request. ---@field id string +--- ---The method to unregister for. ---@field method string ---The initialize parameters ----@class lsp._InitializeParams +---@class lsp._InitializeParams: lsp.WorkDoneProgressParams +--- ---The process Id of the parent process that started ---the server. --- ---Is `null` if the process has not been started by another process. ---If the parent process is not alive then the server should exit. ---@field processId integer|lsp.null +--- ---Information about the client --- ---@since 3.15.0 ----@field clientInfo? anonym11 +---@field clientInfo? lsp._anonym11.clientInfo +--- ---The locale the client is currently showing the user interface ---in. This must not necessarily be the locale of the operating ---system. @@ -1998,25 +2358,31 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@field locale? string +--- ---The rootPath of the workspace. Is null ---if no folder is open. --- ---@deprecated in favour of rootUri. ---@field rootPath? string|lsp.null +--- ---The rootUri of the workspace. Is null if no ---folder is open. If both `rootPath` and `rootUri` are set ---`rootUri` wins. --- ---@deprecated in favour of workspaceFolders. ---@field rootUri lsp.DocumentUri|lsp.null +--- ---The capabilities provided by the client (editor or tool) ---@field capabilities lsp.ClientCapabilities +--- ---User provided initialization options. ---@field initializationOptions? lsp.LSPAny +--- ---The initial trace setting. If omitted trace is disabled ('off'). ---@field trace? lsp.TraceValues ---@class lsp.WorkspaceFoldersInitializeParams +--- ---The workspace folders configured in the client when the server starts. --- ---This property is only available if the client supports workspace folders. @@ -2029,6 +2395,7 @@ error('Cannot require a meta file') ---Defines the capabilities provided by a language ---server. ---@class lsp.ServerCapabilities +--- ---The position encoding the server picked from the encodings offered ---by the client via the client capability `general.positionEncodings`. --- @@ -2039,126 +2406,167 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@field positionEncoding? lsp.PositionEncodingKind +--- ---Defines how text documents are synced. Is either a detailed structure ---defining each notification or for backwards compatibility the ---TextDocumentSyncKind number. ---@field textDocumentSync? lsp.TextDocumentSyncOptions|lsp.TextDocumentSyncKind +--- ---Defines how notebook documents are synced. --- ---@since 3.17.0 ---@field notebookDocumentSync? lsp.NotebookDocumentSyncOptions|lsp.NotebookDocumentSyncRegistrationOptions +--- ---The server provides completion support. ---@field completionProvider? lsp.CompletionOptions +--- ---The server provides hover support. ---@field hoverProvider? boolean|lsp.HoverOptions +--- ---The server provides signature help support. ---@field signatureHelpProvider? lsp.SignatureHelpOptions +--- ---The server provides Goto Declaration support. ---@field declarationProvider? boolean|lsp.DeclarationOptions|lsp.DeclarationRegistrationOptions +--- ---The server provides goto definition support. ---@field definitionProvider? boolean|lsp.DefinitionOptions +--- ---The server provides Goto Type Definition support. ---@field typeDefinitionProvider? boolean|lsp.TypeDefinitionOptions|lsp.TypeDefinitionRegistrationOptions +--- ---The server provides Goto Implementation support. ---@field implementationProvider? boolean|lsp.ImplementationOptions|lsp.ImplementationRegistrationOptions +--- ---The server provides find references support. ---@field referencesProvider? boolean|lsp.ReferenceOptions +--- ---The server provides document highlight support. ---@field documentHighlightProvider? boolean|lsp.DocumentHighlightOptions +--- ---The server provides document symbol support. ---@field documentSymbolProvider? boolean|lsp.DocumentSymbolOptions +--- ---The server provides code actions. CodeActionOptions may only be ---specified if the client states that it supports ---`codeActionLiteralSupport` in its initial `initialize` request. ---@field codeActionProvider? boolean|lsp.CodeActionOptions +--- ---The server provides code lens. ---@field codeLensProvider? lsp.CodeLensOptions +--- ---The server provides document link support. ---@field documentLinkProvider? lsp.DocumentLinkOptions +--- ---The server provides color provider support. ---@field colorProvider? boolean|lsp.DocumentColorOptions|lsp.DocumentColorRegistrationOptions +--- ---The server provides workspace symbol support. ---@field workspaceSymbolProvider? boolean|lsp.WorkspaceSymbolOptions +--- ---The server provides document formatting. ---@field documentFormattingProvider? boolean|lsp.DocumentFormattingOptions +--- ---The server provides document range formatting. ---@field documentRangeFormattingProvider? boolean|lsp.DocumentRangeFormattingOptions +--- ---The server provides document formatting on typing. ---@field documentOnTypeFormattingProvider? lsp.DocumentOnTypeFormattingOptions +--- ---The server provides rename support. RenameOptions may only be ---specified if the client states that it supports ---`prepareSupport` in its initial `initialize` request. ---@field renameProvider? boolean|lsp.RenameOptions +--- ---The server provides folding provider support. ---@field foldingRangeProvider? boolean|lsp.FoldingRangeOptions|lsp.FoldingRangeRegistrationOptions +--- ---The server provides selection range support. ---@field selectionRangeProvider? boolean|lsp.SelectionRangeOptions|lsp.SelectionRangeRegistrationOptions +--- ---The server provides execute command support. ---@field executeCommandProvider? lsp.ExecuteCommandOptions +--- ---The server provides call hierarchy support. --- ---@since 3.16.0 ---@field callHierarchyProvider? boolean|lsp.CallHierarchyOptions|lsp.CallHierarchyRegistrationOptions +--- ---The server provides linked editing range support. --- ---@since 3.16.0 ---@field linkedEditingRangeProvider? boolean|lsp.LinkedEditingRangeOptions|lsp.LinkedEditingRangeRegistrationOptions +--- ---The server provides semantic tokens support. --- ---@since 3.16.0 ---@field semanticTokensProvider? lsp.SemanticTokensOptions|lsp.SemanticTokensRegistrationOptions +--- ---The server provides moniker support. --- ---@since 3.16.0 ---@field monikerProvider? boolean|lsp.MonikerOptions|lsp.MonikerRegistrationOptions +--- ---The server provides type hierarchy support. --- ---@since 3.17.0 ---@field typeHierarchyProvider? boolean|lsp.TypeHierarchyOptions|lsp.TypeHierarchyRegistrationOptions +--- ---The server provides inline values. --- ---@since 3.17.0 ---@field inlineValueProvider? boolean|lsp.InlineValueOptions|lsp.InlineValueRegistrationOptions +--- ---The server provides inlay hints. --- ---@since 3.17.0 ---@field inlayHintProvider? boolean|lsp.InlayHintOptions|lsp.InlayHintRegistrationOptions +--- ---The server has support for pull model diagnostics. --- ---@since 3.17.0 ---@field diagnosticProvider? lsp.DiagnosticOptions|lsp.DiagnosticRegistrationOptions +--- ---Inline completion options used during static registration. --- ---@since 3.18.0 ---@proposed ---@field inlineCompletionProvider? boolean|lsp.InlineCompletionOptions +--- ---Workspace specific server capabilities. ----@field workspace? anonym12 +---@field workspace? lsp._anonym12.workspace +--- ---Experimental server capabilities. ---@field experimental? lsp.LSPAny ---A text document identifier to denote a specific version of a text document. ---@class lsp.VersionedTextDocumentIdentifier: lsp.TextDocumentIdentifier +--- ---The version number of this document. ---@field version integer ---Save options. ---@class lsp.SaveOptions +--- ---The client is supposed to include the content on save. ---@field includeText? boolean ---An event describing a file change. ---@class lsp.FileEvent +--- ---The file's uri. ---@field uri lsp.DocumentUri +--- ---The change type. ---@field type lsp.FileChangeType ---@class lsp.FileSystemWatcher +--- ---The glob pattern to watch. See {@link GlobPattern glob pattern} for more detail. --- ---@since 3.17.0 support for relative patterns. ---@field globPattern lsp.GlobPattern +--- ---The kind of events of interest. If omitted it defaults ---to WatchKind.Create | WatchKind.Change | WatchKind.Delete ---which is 7. @@ -2167,31 +2575,40 @@ error('Cannot require a meta file') ---Represents a diagnostic, such as a compiler error or warning. Diagnostic objects ---are only valid in the scope of a resource. ---@class lsp.Diagnostic +--- ---The range at which the message applies ---@field range lsp.Range +--- ---The diagnostic's severity. Can be omitted. If omitted it is up to the ---client to interpret diagnostics as error, warning, info or hint. ---@field severity? lsp.DiagnosticSeverity +--- ---The diagnostic's code, which usually appear in the user interface. ---@field code? integer|string +--- ---An optional property to describe the error code. ---Requires the code field (above) to be present/not null. --- ---@since 3.16.0 ---@field codeDescription? lsp.CodeDescription +--- ---A human-readable string describing the source of this ---diagnostic, e.g. 'typescript' or 'super lint'. It usually ---appears in the user interface. ---@field source? string +--- ---The diagnostic's message. It usually appears in the user interface ---@field message string +--- ---Additional metadata about the diagnostic. --- ---@since 3.15.0 ---@field tags? lsp.DiagnosticTag[] +--- ---An array of related diagnostic information, e.g. when symbol-names within ---a scope collide all definitions can be marked via this property. ---@field relatedInformation? lsp.DiagnosticRelatedInformation[] +--- ---A data entry field that is preserved between a `textDocument/publishDiagnostics` ---notification and `textDocument/codeAction` request. --- @@ -2200,8 +2617,10 @@ error('Cannot require a meta file') ---Contains additional information about the context in which a completion request is triggered. ---@class lsp.CompletionContext +--- ---How the completion was triggered. ---@field triggerKind lsp.CompletionTriggerKind +--- ---The trigger character (a single character) that has trigger code complete. ---Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter` ---@field triggerCharacter? string @@ -2210,9 +2629,11 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.CompletionItemLabelDetails +--- ---An optional string which is rendered less prominently directly after {@link CompletionItem.label label}, ---without any spacing. Should be used for function signatures and type annotations. ---@field detail? string +--- ---An optional string which is rendered less prominently after {@link CompletionItem.detail}. Should be used ---for fully qualified names and file paths. ---@field description? string @@ -2221,15 +2642,19 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.InsertReplaceEdit +--- ---The string to be inserted. ---@field newText string +--- ---The range if the insert is requested ---@field insert lsp.Range +--- ---The range if the replace is requested. ---@field replace lsp.Range ---Completion options. ----@class lsp.CompletionOptions +---@class lsp.CompletionOptions: lsp.WorkDoneProgressOptions +--- ---Most tools trigger completion request automatically without explicitly requesting ---it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user ---starts to type an identifier. For example if the user types `c` in a JavaScript file @@ -2239,6 +2664,7 @@ error('Cannot require a meta file') ---If code complete should automatically be trigger on characters not being valid inside ---an identifier (for example `.` in JavaScript) list them in `triggerCharacters`. ---@field triggerCharacters? string[] +--- ---The list of all possible characters that commit a completion. This field can be used ---if clients don't support individual commit characters per completion item. See ---`ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport` @@ -2248,33 +2674,39 @@ error('Cannot require a meta file') --- ---@since 3.2.0 ---@field allCommitCharacters? string[] +--- ---The server provides support to resolve additional ---information for a completion item. ---@field resolveProvider? boolean +--- ---The server supports the following `CompletionItem` specific ---capabilities. --- ---@since 3.17.0 ----@field completionItem? anonym13 +---@field completionItem? lsp._anonym13.completionItem ---Hover options. ----@class lsp.HoverOptions +---@class lsp.HoverOptions: lsp.WorkDoneProgressOptions ---Additional information about the context in which a signature help request was triggered. --- ---@since 3.15.0 ---@class lsp.SignatureHelpContext +--- ---Action that caused signature help to be triggered. ---@field triggerKind lsp.SignatureHelpTriggerKind +--- ---Character that caused signature help to be triggered. --- ---This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter` ---@field triggerCharacter? string +--- ---`true` if signature help was already showing when it was triggered. --- ---Retriggers occurs when the signature help is already active and can be caused by actions such as ---typing a trigger character, a cursor move, or document content changes. ---@field isRetrigger boolean +--- ---The currently active `SignatureHelp`. --- ---The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on @@ -2285,14 +2717,18 @@ error('Cannot require a meta file') ---can have a label, like a function-name, a doc-comment, and ---a set of parameters. ---@class lsp.SignatureInformation +--- ---The label of this signature. Will be shown in ---the UI. ---@field label string +--- ---The human-readable doc-comment of this signature. Will be shown ---in the UI but can be omitted. ---@field documentation? string|lsp.MarkupContent +--- ---The parameters of this signature. ---@field parameters? lsp.ParameterInformation[] +--- ---The index of the active parameter. --- ---If `null`, no parameter of the signature is active (for example a named @@ -2307,9 +2743,11 @@ error('Cannot require a meta file') ---@field activeParameter? uinteger|lsp.null ---Server Capabilities for a {@link SignatureHelpRequest}. ----@class lsp.SignatureHelpOptions +---@class lsp.SignatureHelpOptions: lsp.WorkDoneProgressOptions +--- ---List of characters that trigger signature help automatically. ---@field triggerCharacters? string[] +--- ---List of characters that re-trigger signature help. --- ---These trigger characters are only active when signature help is already showing. All trigger characters @@ -2319,30 +2757,35 @@ error('Cannot require a meta file') ---@field retriggerCharacters? string[] ---Server Capabilities for a {@link DefinitionRequest}. ----@class lsp.DefinitionOptions +---@class lsp.DefinitionOptions: lsp.WorkDoneProgressOptions ---Value-object that contains additional information when ---requesting references. ---@class lsp.ReferenceContext +--- ---Include the declaration of the current symbol. ---@field includeDeclaration boolean ---Reference options. ----@class lsp.ReferenceOptions +---@class lsp.ReferenceOptions: lsp.WorkDoneProgressOptions ---Provider options for a {@link DocumentHighlightRequest}. ----@class lsp.DocumentHighlightOptions +---@class lsp.DocumentHighlightOptions: lsp.WorkDoneProgressOptions ---A base for all symbol information. ---@class lsp.BaseSymbolInformation +--- ---The name of this symbol. ---@field name string +--- ---The kind of this symbol. ---@field kind lsp.SymbolKind +--- ---Tags for this symbol. --- ---@since 3.16.0 ---@field tags? lsp.SymbolTag[] +--- ---The name of the symbol containing this symbol. This information is for ---user interface purposes (e.g. to render a qualifier in the user interface ---if necessary). It can't be used to re-infer a hierarchy for the document @@ -2350,7 +2793,8 @@ error('Cannot require a meta file') ---@field containerName? string ---Provider options for a {@link DocumentSymbolRequest}. ----@class lsp.DocumentSymbolOptions +---@class lsp.DocumentSymbolOptions: lsp.WorkDoneProgressOptions +--- ---A human-readable string that is shown when multiple outlines trees ---are shown for the same document. --- @@ -2360,29 +2804,34 @@ error('Cannot require a meta file') ---Contains additional diagnostic information about the context in which ---a {@link CodeActionProvider.provideCodeActions code action} is run. ---@class lsp.CodeActionContext +--- ---An array of diagnostics known on the client side overlapping the range provided to the ---`textDocument/codeAction` request. They are provided so that the server knows which ---errors are currently presented to the user for the given range. There is no guarantee ---that these accurately reflect the error state of the resource. The primary parameter ---to compute code actions is the provided range. ---@field diagnostics lsp.Diagnostic[] +--- ---Requested kind of actions to return. --- ---Actions not of this kind are filtered out by the client before being shown. So servers ---can omit computing them. ---@field only? lsp.CodeActionKind[] +--- ---The reason why code actions were requested. --- ---@since 3.17.0 ---@field triggerKind? lsp.CodeActionTriggerKind ---Provider options for a {@link CodeActionRequest}. ----@class lsp.CodeActionOptions +---@class lsp.CodeActionOptions: lsp.WorkDoneProgressOptions +--- ---CodeActionKinds that this server may return. --- ---The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server ---may list out every specific kind they provide. ---@field codeActionKinds? lsp.CodeActionKind[] +--- ---The server provides support to resolve additional ---information for a code action. --- @@ -2390,7 +2839,8 @@ error('Cannot require a meta file') ---@field resolveProvider? boolean ---Server capabilities for a {@link WorkspaceSymbolRequest}. ----@class lsp.WorkspaceSymbolOptions +---@class lsp.WorkspaceSymbolOptions: lsp.WorkDoneProgressOptions +--- ---The server provides support to resolve additional ---information for a workspace symbol. --- @@ -2398,39 +2848,47 @@ error('Cannot require a meta file') ---@field resolveProvider? boolean ---Code Lens provider options of a {@link CodeLensRequest}. ----@class lsp.CodeLensOptions +---@class lsp.CodeLensOptions: lsp.WorkDoneProgressOptions +--- ---Code lens has a resolve provider as well. ---@field resolveProvider? boolean ---Provider options for a {@link DocumentLinkRequest}. ----@class lsp.DocumentLinkOptions +---@class lsp.DocumentLinkOptions: lsp.WorkDoneProgressOptions +--- ---Document links have a resolve provider as well. ---@field resolveProvider? boolean ---Value-object describing what options formatting should use. ---@class lsp.FormattingOptions +--- ---Size of a tab in spaces. ---@field tabSize uinteger +--- ---Prefer spaces over tabs. ---@field insertSpaces boolean +--- ---Trim trailing whitespace on a line. --- ---@since 3.15.0 ---@field trimTrailingWhitespace? boolean +--- ---Insert a newline character at the end of the file if one does not exist. --- ---@since 3.15.0 ---@field insertFinalNewline? boolean +--- ---Trim all newlines after the final newline at the end of the file. --- ---@since 3.15.0 ---@field trimFinalNewlines? boolean ---Provider options for a {@link DocumentFormattingRequest}. ----@class lsp.DocumentFormattingOptions +---@class lsp.DocumentFormattingOptions: lsp.WorkDoneProgressOptions ---Provider options for a {@link DocumentRangeFormattingRequest}. ----@class lsp.DocumentRangeFormattingOptions +---@class lsp.DocumentRangeFormattingOptions: lsp.WorkDoneProgressOptions +--- ---Whether the server supports formatting multiple ranges at once. --- ---@since 3.18.0 @@ -2439,32 +2897,39 @@ error('Cannot require a meta file') ---Provider options for a {@link DocumentOnTypeFormattingRequest}. ---@class lsp.DocumentOnTypeFormattingOptions +--- ---A character on which formatting should be triggered, like `{`. ---@field firstTriggerCharacter string +--- ---More trigger characters. ---@field moreTriggerCharacter? string[] ---Provider options for a {@link RenameRequest}. ----@class lsp.RenameOptions +---@class lsp.RenameOptions: lsp.WorkDoneProgressOptions +--- ---Renames should be checked and tested before being executed. --- ---@since version 3.12.0 ---@field prepareProvider? boolean ---The server capabilities of a {@link ExecuteCommandRequest}. ----@class lsp.ExecuteCommandOptions +---@class lsp.ExecuteCommandOptions: lsp.WorkDoneProgressOptions +--- ---The commands to be executed on the server ---@field commands string[] ---@since 3.16.0 ---@class lsp.SemanticTokensLegend +--- ---The token types a server uses. ---@field tokenTypes string[] +--- ---The token modifiers a server uses. ---@field tokenModifiers string[] ---A text document identifier to optionally denote a specific version of a text document. ---@class lsp.OptionalVersionedTextDocumentIdentifier: lsp.TextDocumentIdentifier +--- ---The version number of this document. If a versioned text document identifier ---is sent from the server to the client and the file is not open in the editor ---(the server has not received an open notification before) the server can send @@ -2476,13 +2941,16 @@ error('Cannot require a meta file') --- ---@since 3.16.0. ---@class lsp.AnnotatedTextEdit: lsp.TextEdit +--- ---The actual identifier of the change annotation ---@field annotationId lsp.ChangeAnnotationIdentifier ---A generic resource operation. ---@class lsp.ResourceOperation +--- ---The resource operation kind. ---@field kind string +--- ---An optional annotation identifier describing the operation. --- ---@since 3.16.0 @@ -2490,22 +2958,28 @@ error('Cannot require a meta file') ---Options to create a file. ---@class lsp.CreateFileOptions +--- ---Overwrite existing file. Overwrite wins over `ignoreIfExists` ---@field overwrite? boolean +--- ---Ignore if exists. ---@field ignoreIfExists? boolean ---Rename file options ---@class lsp.RenameFileOptions +--- ---Overwrite target if existing. Overwrite wins over `ignoreIfExists` ---@field overwrite? boolean +--- ---Ignores if target exists. ---@field ignoreIfExists? boolean ---Delete file options ---@class lsp.DeleteFileOptions +--- ---Delete the content recursively if a folder is denoted. ---@field recursive? boolean +--- ---Ignore the operation if the file doesn't exist. ---@field ignoreIfNotExists? boolean @@ -2514,18 +2988,21 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileOperationPattern +--- ---The glob pattern to match. Glob patterns can have the following syntax: ---- `*` 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 sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files) +---- `{}` to group sub patterns into an OR expression. (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`) ---@field glob string +--- ---Whether to match files or folders with this pattern. --- ---Matches both if undefined. ---@field matches? lsp.FileOperationPatternKind +--- ---Additional options used during matching. ---@field options? lsp.FileOperationPatternOptions @@ -2533,8 +3010,10 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.WorkspaceFullDocumentDiagnosticReport: lsp.FullDocumentDiagnosticReport +--- ---The URI for which diagnostic information is reported. ---@field uri lsp.DocumentUri +--- ---The version number for which the diagnostics are reported. ---If the document is not marked as open `null` can be provided. ---@field version integer|lsp.null @@ -2543,8 +3022,10 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.WorkspaceUnchangedDocumentDiagnosticReport: lsp.UnchangedDocumentDiagnosticReport +--- ---The URI for which diagnostic information is reported. ---@field uri lsp.DocumentUri +--- ---The version number for which the diagnostics are reported. ---If the document is not marked as open `null` can be provided. ---@field version integer|lsp.null @@ -2557,15 +3038,19 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookCell +--- ---The cell's kind ---@field kind lsp.NotebookCellKind +--- ---The URI of the cell's text document ---content. ---@field document lsp.DocumentUri +--- ---Additional metadata stored with the cell. --- ---Note: should always be an object literal (e.g. LSPObject) ---@field metadata? lsp.LSPObject +--- ---Additional execution summary information ---if supported by the client. ---@field executionSummary? lsp.ExecutionSummary @@ -2575,10 +3060,13 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookCellArrayChange +--- ---The start oftest of the cell that changed. ---@field start uinteger +--- ---The deleted cells ---@field deleteCount uinteger +--- ---The new cells, if any ---@field cells? lsp.NotebookCell[] @@ -2587,43 +3075,56 @@ error('Cannot require a meta file') ---@since 3.18.0 ---@proposed ---@class lsp.SelectedCompletionInfo +--- ---The range that will be replaced if this completion item is accepted. ---@field range lsp.Range +--- ---The text the range will be replaced with if this completion is accepted. ---@field text string ---Defines the capabilities provided by the client. ---@class lsp.ClientCapabilities +--- ---Workspace specific client capabilities. ---@field workspace? lsp.WorkspaceClientCapabilities +--- ---Text document specific client capabilities. ---@field textDocument? lsp.TextDocumentClientCapabilities +--- ---Capabilities specific to the notebook document support. --- ---@since 3.17.0 ---@field notebookDocument? lsp.NotebookDocumentClientCapabilities +--- ---Window specific client capabilities. ---@field window? lsp.WindowClientCapabilities +--- ---General client capabilities. --- ---@since 3.16.0 ---@field general? lsp.GeneralClientCapabilities +--- ---Experimental client capabilities. ---@field experimental? lsp.LSPAny ---@class lsp.TextDocumentSyncOptions +--- ---Open and close notifications are sent to the server. If omitted open close notification should not ---be sent. ---@field openClose? boolean +--- ---Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full ---and TextDocumentSyncKind.Incremental. If omitted it defaults to TextDocumentSyncKind.None. ---@field change? lsp.TextDocumentSyncKind +--- ---If present will save notifications are sent to the server. If omitted the notification should not be ---sent. ---@field willSave? boolean +--- ---If present will save wait until requests are sent to the server. If omitted the request should not be ---sent. ---@field willSaveWaitUntil? boolean +--- ---If present save notifications are sent to the server. If omitted the notification should not be ---sent. ---@field save? boolean|lsp.SaveOptions @@ -2642,8 +3143,10 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookDocumentSyncOptions +--- ---The notebooks to be synced ----@field notebookSelector anonym15|anonym17[] +---@field notebookSelector lsp._anonym14.notebookSelector|lsp._anonym16.notebookSelector[] +--- ---Whether save notification should be forwarded to ---the server. Will only be honored if mode === `notebook`. ---@field save? boolean @@ -2654,8 +3157,10 @@ error('Cannot require a meta file') ---@class lsp.NotebookDocumentSyncRegistrationOptions: lsp.NotebookDocumentSyncOptions, lsp.StaticRegistrationOptions ---@class lsp.WorkspaceFoldersServerCapabilities +--- ---The server has support for workspace folders ---@field supported? boolean +--- ---Whether the server wants to receive workspace folder ---change notifications. --- @@ -2669,16 +3174,22 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileOperationOptions +--- ---The server is interested in receiving didCreateFiles notifications. ---@field didCreate? lsp.FileOperationRegistrationOptions +--- ---The server is interested in receiving willCreateFiles requests. ---@field willCreate? lsp.FileOperationRegistrationOptions +--- ---The server is interested in receiving didRenameFiles notifications. ---@field didRename? lsp.FileOperationRegistrationOptions +--- ---The server is interested in receiving willRenameFiles requests. ---@field willRename? lsp.FileOperationRegistrationOptions +--- ---The server is interested in receiving didDeleteFiles file notifications. ---@field didDelete? lsp.FileOperationRegistrationOptions +--- ---The server is interested in receiving willDeleteFiles file requests. ---@field willDelete? lsp.FileOperationRegistrationOptions @@ -2686,6 +3197,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.CodeDescription +--- ---An URI to open with more information about the diagnostic error. ---@field href lsp.URI @@ -2693,14 +3205,17 @@ error('Cannot require a meta file') ---used to point to code locations that cause or related to a diagnostics, e.g when duplicating ---a symbol in a scope. ---@class lsp.DiagnosticRelatedInformation +--- ---The location of this related diagnostic information. ---@field location lsp.Location +--- ---The message of this related diagnostic information. ---@field message string ---Represents a parameter of a callable-signature. A parameter can ---have a label and a doc-comment. ---@class lsp.ParameterInformation +--- ---The label of this parameter information. --- ---Either a string or an inclusive start and exclusive end offsets within its containing @@ -2710,6 +3225,7 @@ error('Cannot require a meta file') ---*Note*: a label of type string should be a substring of its containing signature label. ---Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`. ---@field label string|{ [1]: uinteger, [2]: uinteger } +--- ---The human-readable doc-comment of this parameter. Will be shown ---in the UI but can be omitted. ---@field documentation? string|lsp.MarkupContent @@ -2719,11 +3235,13 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookCellTextDocumentFilter +--- ---A filter that matches against the notebook ---containing the notebook cell. If a string ---value is provided it matches against the ---notebook type. '*' matches every notebook. ---@field notebook string|lsp.NotebookDocumentFilter +--- ---A language id like `python`. --- ---Will be matched against the language id of the @@ -2734,71 +3252,89 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileOperationPatternOptions +--- ---The pattern should be matched ignoring casing. ---@field ignoreCase? boolean ---@class lsp.ExecutionSummary +--- ---A strict monotonically increasing value ---indicating the execution order of a cell ---inside a notebook. ---@field executionOrder uinteger +--- ---Whether the execution was successful or ---not if known by the client. ---@field success? boolean ---Workspace specific client capabilities. ---@class lsp.WorkspaceClientCapabilities +--- ---The client supports applying batch edits ---to the workspace by supporting the request ---'workspace/applyEdit' ---@field applyEdit? boolean +--- ---Capabilities specific to `WorkspaceEdit`s. ---@field workspaceEdit? lsp.WorkspaceEditClientCapabilities +--- ---Capabilities specific to the `workspace/didChangeConfiguration` notification. ---@field didChangeConfiguration? lsp.DidChangeConfigurationClientCapabilities +--- ---Capabilities specific to the `workspace/didChangeWatchedFiles` notification. ---@field didChangeWatchedFiles? lsp.DidChangeWatchedFilesClientCapabilities +--- ---Capabilities specific to the `workspace/symbol` request. ---@field symbol? lsp.WorkspaceSymbolClientCapabilities +--- ---Capabilities specific to the `workspace/executeCommand` request. ---@field executeCommand? lsp.ExecuteCommandClientCapabilities +--- ---The client has support for workspace folders. --- ---@since 3.6.0 ---@field workspaceFolders? boolean +--- ---The client supports `workspace/configuration` requests. --- ---@since 3.6.0 ---@field configuration? boolean +--- ---Capabilities specific to the semantic token requests scoped to the ---workspace. --- ---@since 3.16.0. ---@field semanticTokens? lsp.SemanticTokensWorkspaceClientCapabilities +--- ---Capabilities specific to the code lens requests scoped to the ---workspace. --- ---@since 3.16.0. ---@field codeLens? lsp.CodeLensWorkspaceClientCapabilities +--- ---The client has support for file notifications/requests for user operations on files. --- ---Since 3.16.0 ---@field fileOperations? lsp.FileOperationClientCapabilities +--- ---Capabilities specific to the inline values requests scoped to the ---workspace. --- ---@since 3.17.0. ---@field inlineValue? lsp.InlineValueWorkspaceClientCapabilities +--- ---Capabilities specific to the inlay hint requests scoped to the ---workspace. --- ---@since 3.17.0. ---@field inlayHint? lsp.InlayHintWorkspaceClientCapabilities +--- ---Capabilities specific to the diagnostic requests scoped to the ---workspace. --- ---@since 3.17.0. ---@field diagnostics? lsp.DiagnosticWorkspaceClientCapabilities +--- ---Capabilities specific to the folding range requests scoped to the workspace. --- ---@since 3.18.0 @@ -2807,95 +3343,126 @@ error('Cannot require a meta file') ---Text document specific client capabilities. ---@class lsp.TextDocumentClientCapabilities +--- ---Defines which synchronization capabilities the client supports. ---@field synchronization? lsp.TextDocumentSyncClientCapabilities +--- ---Capabilities specific to the `textDocument/completion` request. ---@field completion? lsp.CompletionClientCapabilities +--- ---Capabilities specific to the `textDocument/hover` request. ---@field hover? lsp.HoverClientCapabilities +--- ---Capabilities specific to the `textDocument/signatureHelp` request. ---@field signatureHelp? lsp.SignatureHelpClientCapabilities +--- ---Capabilities specific to the `textDocument/declaration` request. --- ---@since 3.14.0 ---@field declaration? lsp.DeclarationClientCapabilities +--- ---Capabilities specific to the `textDocument/definition` request. ---@field definition? lsp.DefinitionClientCapabilities +--- ---Capabilities specific to the `textDocument/typeDefinition` request. --- ---@since 3.6.0 ---@field typeDefinition? lsp.TypeDefinitionClientCapabilities +--- ---Capabilities specific to the `textDocument/implementation` request. --- ---@since 3.6.0 ---@field implementation? lsp.ImplementationClientCapabilities +--- ---Capabilities specific to the `textDocument/references` request. ---@field references? lsp.ReferenceClientCapabilities +--- ---Capabilities specific to the `textDocument/documentHighlight` request. ---@field documentHighlight? lsp.DocumentHighlightClientCapabilities +--- ---Capabilities specific to the `textDocument/documentSymbol` request. ---@field documentSymbol? lsp.DocumentSymbolClientCapabilities +--- ---Capabilities specific to the `textDocument/codeAction` request. ---@field codeAction? lsp.CodeActionClientCapabilities +--- ---Capabilities specific to the `textDocument/codeLens` request. ---@field codeLens? lsp.CodeLensClientCapabilities +--- ---Capabilities specific to the `textDocument/documentLink` request. ---@field documentLink? lsp.DocumentLinkClientCapabilities +--- ---Capabilities specific to the `textDocument/documentColor` and the ---`textDocument/colorPresentation` request. --- ---@since 3.6.0 ---@field colorProvider? lsp.DocumentColorClientCapabilities +--- ---Capabilities specific to the `textDocument/formatting` request. ---@field formatting? lsp.DocumentFormattingClientCapabilities +--- ---Capabilities specific to the `textDocument/rangeFormatting` request. ---@field rangeFormatting? lsp.DocumentRangeFormattingClientCapabilities +--- ---Capabilities specific to the `textDocument/onTypeFormatting` request. ---@field onTypeFormatting? lsp.DocumentOnTypeFormattingClientCapabilities +--- ---Capabilities specific to the `textDocument/rename` request. ---@field rename? lsp.RenameClientCapabilities +--- ---Capabilities specific to the `textDocument/foldingRange` request. --- ---@since 3.10.0 ---@field foldingRange? lsp.FoldingRangeClientCapabilities +--- ---Capabilities specific to the `textDocument/selectionRange` request. --- ---@since 3.15.0 ---@field selectionRange? lsp.SelectionRangeClientCapabilities +--- ---Capabilities specific to the `textDocument/publishDiagnostics` notification. ---@field publishDiagnostics? lsp.PublishDiagnosticsClientCapabilities +--- ---Capabilities specific to the various call hierarchy requests. --- ---@since 3.16.0 ---@field callHierarchy? lsp.CallHierarchyClientCapabilities +--- ---Capabilities specific to the various semantic token request. --- ---@since 3.16.0 ---@field semanticTokens? lsp.SemanticTokensClientCapabilities +--- ---Capabilities specific to the `textDocument/linkedEditingRange` request. --- ---@since 3.16.0 ---@field linkedEditingRange? lsp.LinkedEditingRangeClientCapabilities +--- ---Client capabilities specific to the `textDocument/moniker` request. --- ---@since 3.16.0 ---@field moniker? lsp.MonikerClientCapabilities +--- ---Capabilities specific to the various type hierarchy requests. --- ---@since 3.17.0 ---@field typeHierarchy? lsp.TypeHierarchyClientCapabilities +--- ---Capabilities specific to the `textDocument/inlineValue` request. --- ---@since 3.17.0 ---@field inlineValue? lsp.InlineValueClientCapabilities +--- ---Capabilities specific to the `textDocument/inlayHint` request. --- ---@since 3.17.0 ---@field inlayHint? lsp.InlayHintClientCapabilities +--- ---Capabilities specific to the diagnostic pull model. --- ---@since 3.17.0 ---@field diagnostic? lsp.DiagnosticClientCapabilities +--- ---Client capabilities specific to inline completions. --- ---@since 3.18.0 @@ -2906,12 +3473,14 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookDocumentClientCapabilities +--- ---Capabilities specific to notebook document synchronization --- ---@since 3.17.0 ---@field synchronization lsp.NotebookDocumentSyncClientCapabilities ---@class lsp.WindowClientCapabilities +--- ---It indicates whether the client supports server initiated ---progress using the `window/workDoneProgress/create` request. --- @@ -2922,10 +3491,12 @@ error('Cannot require a meta file') --- ---@since 3.15.0 ---@field workDoneProgress? boolean +--- ---Capabilities specific to the showMessage request. --- ---@since 3.16.0 ---@field showMessage? lsp.ShowMessageRequestClientCapabilities +--- ---Capabilities specific to the showDocument request. --- ---@since 3.16.0 @@ -2935,21 +3506,25 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.GeneralClientCapabilities +--- ---Client capability that signals how the client ---handles stale requests (e.g. a request ---for which the client will not process the response ---anymore since the information is outdated). --- ---@since 3.17.0 ----@field staleRequestSupport? anonym18 +---@field staleRequestSupport? lsp._anonym18.staleRequestSupport +--- ---Client capabilities specific to regular expressions. --- ---@since 3.16.0 ---@field regularExpressions? lsp.RegularExpressionsClientCapabilities +--- ---Client capabilities specific to the client's markdown parser. --- ---@since 3.16.0 ---@field markdown? lsp.MarkdownClientCapabilities +--- ---The position encodings supported by the client. Client and server ---have to agree on the same position encoding to ensure that offsets ---(e.g. character position in a line) are interpreted the same on both @@ -2976,25 +3551,31 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.RelativePattern +--- ---A workspace folder or a base URI to which this pattern will be matched ---against relatively. ---@field baseUri lsp.WorkspaceFolder|lsp.URI +--- ---The actual glob pattern; ---@field pattern lsp.Pattern ---@class lsp.WorkspaceEditClientCapabilities +--- ---The client supports versioned document changes in `WorkspaceEdit`s ---@field documentChanges? boolean +--- ---The resource operations the client supports. Clients should at least ---support 'create', 'rename' and 'delete' files and folders. --- ---@since 3.13.0 ---@field resourceOperations? lsp.ResourceOperationKind[] +--- ---The failure handling strategy of a client if applying the workspace edit ---fails. --- ---@since 3.13.0 ---@field failureHandling? lsp.FailureHandlingKind +--- ---Whether the client normalizes line endings to the client specific ---setting. ---If set to `true` the client will normalize line ending characters @@ -3003,21 +3584,25 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@field normalizesLineEndings? boolean +--- ---Whether the client in general supports change annotations on text edits, ---create file, rename file and delete file changes. --- ---@since 3.16.0 ----@field changeAnnotationSupport? anonym19 +---@field changeAnnotationSupport? lsp._anonym19.changeAnnotationSupport ---@class lsp.DidChangeConfigurationClientCapabilities +--- ---Did change configuration notification supports dynamic registration. ---@field dynamicRegistration? boolean ---@class lsp.DidChangeWatchedFilesClientCapabilities +--- ---Did change watched files notification supports dynamic registration. Please note ---that the current protocol doesn't support static configuration for file changes ---from the server side. ---@field dynamicRegistration? boolean +--- ---Whether the client has support for {@link RelativePattern relative pattern} ---or not. --- @@ -3026,29 +3611,35 @@ error('Cannot require a meta file') ---Client capabilities for a {@link WorkspaceSymbolRequest}. ---@class lsp.WorkspaceSymbolClientCapabilities +--- ---Symbol request supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. ----@field symbolKind? anonym20 +---@field symbolKind? lsp._anonym20.symbolKind +--- ---The client supports tags on `SymbolInformation`. ---Clients supporting tags have to handle unknown tags gracefully. --- ---@since 3.16.0 ----@field tagSupport? anonym21 +---@field tagSupport? lsp._anonym21.tagSupport +--- ---The client support partial workspace symbols. The client will send the ---request `workspaceSymbol/resolve` to the server to resolve additional ---properties. --- ---@since 3.17.0 ----@field resolveSupport? anonym22 +---@field resolveSupport? lsp._anonym22.resolveSupport ---The client capabilities of a {@link ExecuteCommandRequest}. ---@class lsp.ExecuteCommandClientCapabilities +--- ---Execute command supports dynamic registration. ---@field dynamicRegistration? boolean ---@since 3.16.0 ---@class lsp.SemanticTokensWorkspaceClientCapabilities +--- ---Whether the client implementation supports a refresh request sent from ---the server to the client. --- @@ -3060,6 +3651,7 @@ error('Cannot require a meta file') ---@since 3.16.0 ---@class lsp.CodeLensWorkspaceClientCapabilities +--- ---Whether the client implementation supports a refresh request sent from the ---server to the client. --- @@ -3076,18 +3668,25 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileOperationClientCapabilities +--- ---Whether the client supports dynamic registration for file requests/notifications. ---@field dynamicRegistration? boolean +--- ---The client has support for sending didCreateFiles notifications. ---@field didCreate? boolean +--- ---The client has support for sending willCreateFiles requests. ---@field willCreate? boolean +--- ---The client has support for sending didRenameFiles notifications. ---@field didRename? boolean +--- ---The client has support for sending willRenameFiles requests. ---@field willRename? boolean +--- ---The client has support for sending didDeleteFiles notifications. ---@field didDelete? boolean +--- ---The client has support for sending willDeleteFiles requests. ---@field willDelete? boolean @@ -3095,6 +3694,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlineValueWorkspaceClientCapabilities +--- ---Whether the client implementation supports a refresh request sent from the ---server to the client. --- @@ -3108,6 +3708,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlayHintWorkspaceClientCapabilities +--- ---Whether the client implementation supports a refresh request sent from ---the server to the client. --- @@ -3121,6 +3722,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.DiagnosticWorkspaceClientCapabilities +--- ---Whether the client implementation supports a refresh request sent from ---the server to the client. --- @@ -3135,6 +3737,7 @@ error('Cannot require a meta file') ---@since 3.18.0 ---@proposed ---@class lsp.FoldingRangeWorkspaceClientCapabilities +--- ---Whether the client implementation supports a refresh request sent from the ---server to the client. --- @@ -3148,54 +3751,69 @@ error('Cannot require a meta file') ---@field refreshSupport? boolean ---@class lsp.TextDocumentSyncClientCapabilities +--- ---Whether text document synchronization supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---The client supports sending will save notifications. ---@field willSave? boolean +--- ---The client supports sending a will save request and ---waits for a response providing text edits which will ---be applied to the document before it is saved. ---@field willSaveWaitUntil? boolean +--- ---The client supports did save notifications. ---@field didSave? boolean ---Completion client capabilities ---@class lsp.CompletionClientCapabilities +--- ---Whether completion supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---The client supports the following `CompletionItem` specific ---capabilities. ----@field completionItem? anonym26 ----@field completionItemKind? anonym27 +---@field completionItem? lsp._anonym23.completionItem +--- +---@field completionItemKind? lsp._anonym27.completionItemKind +--- ---Defines how the client handles whitespace and indentation ---when accepting a completion item that uses multi line ---text in either `insertText` or `textEdit`. --- ---@since 3.17.0 ---@field insertTextMode? lsp.InsertTextMode +--- ---The client supports to send additional context information for a ---`textDocument/completion` request. ---@field contextSupport? boolean +--- ---The client supports the following `CompletionList` specific ---capabilities. --- ---@since 3.17.0 ----@field completionList? anonym28 +---@field completionList? lsp._anonym28.completionList ---@class lsp.HoverClientCapabilities +--- ---Whether hover supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---Client supports the following content formats for the content ---property. The order describes the preferred format of the client. ---@field contentFormat? lsp.MarkupKind[] ---Client Capabilities for a {@link SignatureHelpRequest}. ---@class lsp.SignatureHelpClientCapabilities +--- ---Whether signature help supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---The client supports the following `SignatureInformation` ---specific properties. ----@field signatureInformation? anonym30 +---@field signatureInformation? lsp._anonym29.signatureInformation +--- ---The client supports to send additional context information for a ---`textDocument/signatureHelp` request. A client that opts into ---contextSupport will also support the `retriggerCharacters` on @@ -3206,17 +3824,21 @@ error('Cannot require a meta file') ---@since 3.14.0 ---@class lsp.DeclarationClientCapabilities +--- ---Whether declaration supports dynamic registration. If this is set to `true` ---the client supports the new `DeclarationRegistrationOptions` return value ---for the corresponding server capability as well. ---@field dynamicRegistration? boolean +--- ---The client supports additional metadata in the form of declaration links. ---@field linkSupport? boolean ---Client Capabilities for a {@link DefinitionRequest}. ---@class lsp.DefinitionClientCapabilities +--- ---Whether definition supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---The client supports additional metadata in the form of definition links. --- ---@since 3.14.0 @@ -3224,10 +3846,12 @@ error('Cannot require a meta file') ---Since 3.6.0 ---@class lsp.TypeDefinitionClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `TypeDefinitionRegistrationOptions` return value ---for the corresponding server capability as well. ---@field dynamicRegistration? boolean +--- ---The client supports additional metadata in the form of definition links. --- ---Since 3.14.0 @@ -3235,10 +3859,12 @@ error('Cannot require a meta file') ---@since 3.6.0 ---@class lsp.ImplementationClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `ImplementationRegistrationOptions` return value ---for the corresponding server capability as well. ---@field dynamicRegistration? boolean +--- ---The client supports additional metadata in the form of definition links. --- ---@since 3.14.0 @@ -3246,29 +3872,36 @@ error('Cannot require a meta file') ---Client Capabilities for a {@link ReferencesRequest}. ---@class lsp.ReferenceClientCapabilities +--- ---Whether references supports dynamic registration. ---@field dynamicRegistration? boolean ---Client Capabilities for a {@link DocumentHighlightRequest}. ---@class lsp.DocumentHighlightClientCapabilities +--- ---Whether document highlight supports dynamic registration. ---@field dynamicRegistration? boolean ---Client Capabilities for a {@link DocumentSymbolRequest}. ---@class lsp.DocumentSymbolClientCapabilities +--- ---Whether document symbol supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---Specific capabilities for the `SymbolKind` in the ---`textDocument/documentSymbol` request. ----@field symbolKind? anonym31 +---@field symbolKind? lsp._anonym31.symbolKind +--- ---The client supports hierarchical document symbols. ---@field hierarchicalDocumentSymbolSupport? boolean +--- ---The client supports tags on `SymbolInformation`. Tags are supported on ---`DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true. ---Clients supporting tags have to handle unknown tags gracefully. --- ---@since 3.16.0 ----@field tagSupport? anonym32 +---@field tagSupport? lsp._anonym32.tagSupport +--- ---The client supports an additional label presented in the UI when ---registering a document symbol provider. --- @@ -3277,33 +3910,40 @@ error('Cannot require a meta file') ---The Client Capabilities of a {@link CodeActionRequest}. ---@class lsp.CodeActionClientCapabilities +--- ---Whether code action supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---The client support code action literals of type `CodeAction` as a valid ---response of the `textDocument/codeAction` request. If the property is not ---set the request can only return `Command` literals. --- ---@since 3.8.0 ----@field codeActionLiteralSupport? anonym34 +---@field codeActionLiteralSupport? lsp._anonym33.codeActionLiteralSupport +--- ---Whether code action supports the `isPreferred` property. --- ---@since 3.15.0 ---@field isPreferredSupport? boolean +--- ---Whether code action supports the `disabled` property. --- ---@since 3.16.0 ---@field disabledSupport? boolean +--- ---Whether code action supports the `data` property which is ---preserved between a `textDocument/codeAction` and a ---`codeAction/resolve` request. --- ---@since 3.16.0 ---@field dataSupport? boolean +--- ---Whether the client supports resolving additional code action ---properties via a separate `codeAction/resolve` request. --- ---@since 3.16.0 ----@field resolveSupport? anonym35 +---@field resolveSupport? lsp._anonym35.resolveSupport +--- ---Whether the client honors the change annotations in ---text edits and resource operations returned via the ---`CodeAction#edit` property by for example presenting @@ -3315,19 +3955,23 @@ error('Cannot require a meta file') ---The client capabilities of a {@link CodeLensRequest}. ---@class lsp.CodeLensClientCapabilities +--- ---Whether code lens supports dynamic registration. ---@field dynamicRegistration? boolean ---The client capabilities of a {@link DocumentLinkRequest}. ---@class lsp.DocumentLinkClientCapabilities +--- ---Whether document link supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---Whether the client supports the `tooltip` property on `DocumentLink`. --- ---@since 3.15.0 ---@field tooltipSupport? boolean ---@class lsp.DocumentColorClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `DocumentColorRegistrationOptions` return value ---for the corresponding server capability as well. @@ -3335,13 +3979,16 @@ error('Cannot require a meta file') ---Client capabilities of a {@link DocumentFormattingRequest}. ---@class lsp.DocumentFormattingClientCapabilities +--- ---Whether formatting supports dynamic registration. ---@field dynamicRegistration? boolean ---Client capabilities of a {@link DocumentRangeFormattingRequest}. ---@class lsp.DocumentRangeFormattingClientCapabilities +--- ---Whether range formatting supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---Whether the client supports formatting multiple ranges at once. --- ---@since 3.18.0 @@ -3350,17 +3997,21 @@ error('Cannot require a meta file') ---Client capabilities of a {@link DocumentOnTypeFormattingRequest}. ---@class lsp.DocumentOnTypeFormattingClientCapabilities +--- ---Whether on type formatting supports dynamic registration. ---@field dynamicRegistration? boolean ---@class lsp.RenameClientCapabilities +--- ---Whether rename supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---Client supports testing for validity of rename operations ---before execution. --- ---@since 3.12.0 ---@field prepareSupport? boolean +--- ---Client supports the default behavior result. --- ---The value indicates the default behavior used by the @@ -3368,6 +4019,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@field prepareSupportDefaultBehavior? lsp.PrepareSupportDefaultBehavior +--- ---Whether the client honors the change annotations in ---text edits and resource operations returned via the ---rename request's workspace edit by for example presenting @@ -3378,29 +4030,35 @@ error('Cannot require a meta file') ---@field honorsChangeAnnotations? boolean ---@class lsp.FoldingRangeClientCapabilities +--- ---Whether implementation supports dynamic registration for folding range ---providers. If this is set to `true` the client supports the new ---`FoldingRangeRegistrationOptions` return value for the corresponding ---server capability as well. ---@field dynamicRegistration? boolean +--- ---The maximum number of folding ranges that the client prefers to receive ---per document. The value serves as a hint, servers are free to follow the ---limit. ---@field rangeLimit? uinteger +--- ---If set, the client signals that it only supports folding complete lines. ---If set, client will ignore specified `startCharacter` and `endCharacter` ---properties in a FoldingRange. ---@field lineFoldingOnly? boolean +--- ---Specific options for the folding range kind. --- ---@since 3.17.0 ----@field foldingRangeKind? anonym36 +---@field foldingRangeKind? lsp._anonym36.foldingRangeKind +--- ---Specific options for the folding range. --- ---@since 3.17.0 ----@field foldingRange? anonym37 +---@field foldingRange? lsp._anonym37.foldingRange ---@class lsp.SelectionRangeClientCapabilities +--- ---Whether implementation supports dynamic registration for selection range providers. If this is set to `true` ---the client supports the new `SelectionRangeRegistrationOptions` return value for the corresponding server ---capability as well. @@ -3408,22 +4066,27 @@ error('Cannot require a meta file') ---The publish diagnostic client capabilities. ---@class lsp.PublishDiagnosticsClientCapabilities +--- ---Whether the clients accepts diagnostics with related information. ---@field relatedInformation? boolean +--- ---Client supports the tag property to provide meta data about a diagnostic. ---Clients supporting tags have to handle unknown tags gracefully. --- ---@since 3.15.0 ----@field tagSupport? anonym38 +---@field tagSupport? lsp._anonym38.tagSupport +--- ---Whether the client interprets the version property of the ---`textDocument/publishDiagnostics` notification's parameter. --- ---@since 3.15.0 ---@field versionSupport? boolean +--- ---Client supports a codeDescription property --- ---@since 3.16.0 ---@field codeDescriptionSupport? boolean +--- ---Whether code action supports the `data` property which is ---preserved between a `textDocument/publishDiagnostics` and ---`textDocument/codeAction` request. @@ -3433,6 +4096,7 @@ error('Cannot require a meta file') ---@since 3.16.0 ---@class lsp.CallHierarchyClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` ---return value for the corresponding server capability as well. @@ -3440,10 +4104,12 @@ error('Cannot require a meta file') ---@since 3.16.0 ---@class lsp.SemanticTokensClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` ---return value for the corresponding server capability as well. ---@field dynamicRegistration? boolean +--- ---Which requests the client supports and might send to the server ---depending on the server's capability. Please note that clients might not ---show semantic tokens or degrade some of the user experience if a range @@ -3452,17 +4118,23 @@ error('Cannot require a meta file') ---`request.range` are both set to true but the server only provides a ---range provider the client might not render a minimap correctly or might ---even decide to not show any semantic tokens at all. ----@field requests anonym41 +---@field requests lsp._anonym39.requests +--- ---The token types that the client supports. ---@field tokenTypes string[] +--- ---The token modifiers that the client supports. ---@field tokenModifiers string[] +--- ---The token formats the clients supports. ---@field formats lsp.TokenFormat[] +--- ---Whether the client supports tokens that can overlap each other. ---@field overlappingTokenSupport? boolean +--- ---Whether the client supports tokens that can span multiple lines. ---@field multilineTokenSupport? boolean +--- ---Whether the client allows the server to actively cancel a ---semantic token request, e.g. supports returning ---LSPErrorCodes.ServerCancelled. If a server does the client @@ -3470,6 +4142,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@field serverCancelSupport? boolean +--- ---Whether the client uses semantic tokens to augment existing ---syntax tokens. If set to `true` client side created syntax ---tokens and semantic tokens are both used for colorization. If @@ -3486,6 +4159,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.LinkedEditingRangeClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` ---return value for the corresponding server capability as well. @@ -3495,6 +4169,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.MonikerClientCapabilities +--- ---Whether moniker supports dynamic registration. If this is set to `true` ---the client supports the new `MonikerRegistrationOptions` return value ---for the corresponding server capability as well. @@ -3502,6 +4177,7 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@class lsp.TypeHierarchyClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` ---return value for the corresponding server capability as well. @@ -3511,6 +4187,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlineValueClientCapabilities +--- ---Whether implementation supports dynamic registration for inline value providers. ---@field dynamicRegistration? boolean @@ -3518,20 +4195,24 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlayHintClientCapabilities +--- ---Whether inlay hints support dynamic registration. ---@field dynamicRegistration? boolean +--- ---Indicates which properties a client can resolve lazily on an inlay ---hint. ----@field resolveSupport? anonym42 +---@field resolveSupport? lsp._anonym42.resolveSupport ---Client capabilities specific to diagnostic pull requests. --- ---@since 3.17.0 ---@class lsp.DiagnosticClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` ---return value for the corresponding server capability as well. ---@field dynamicRegistration? boolean +--- ---Whether the clients supports related documents for document diagnostic pulls. ---@field relatedDocumentSupport? boolean @@ -3540,6 +4221,7 @@ error('Cannot require a meta file') ---@since 3.18.0 ---@proposed ---@class lsp.InlineCompletionClientCapabilities +--- ---Whether implementation supports dynamic registration for inline completion providers. ---@field dynamicRegistration? boolean @@ -3547,23 +4229,27 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookDocumentSyncClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is ---set to `true` the client supports the new ---`(TextDocumentRegistrationOptions & StaticRegistrationOptions)` ---return value for the corresponding server capability as well. ---@field dynamicRegistration? boolean +--- ---The client supports sending execution summary data per cell. ---@field executionSummarySupport? boolean ---Show message request client capabilities ---@class lsp.ShowMessageRequestClientCapabilities +--- ---Capabilities specific to the `MessageActionItem` type. ----@field messageActionItem? anonym43 +---@field messageActionItem? lsp._anonym43.messageActionItem ---Client capabilities for the showDocument request. --- ---@since 3.16.0 ---@class lsp.ShowDocumentClientCapabilities +--- ---The client has support for the showDocument ---request. ---@field support boolean @@ -3572,8 +4258,10 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.RegularExpressionsClientCapabilities +--- ---The engine's name. ---@field engine string +--- ---The engine's version. ---@field version? string @@ -3581,10 +4269,13 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.MarkdownClientCapabilities +--- ---The name of the parser. ---@field parser string +--- ---The version of the parser. ---@field version? string +--- ---A list of HTML tags that the client allows / supports in ---Markdown. --- @@ -3979,11 +4670,11 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@alias lsp.DocumentDiagnosticReport lsp.RelatedFullDocumentDiagnosticReport|lsp.RelatedUnchangedDocumentDiagnosticReport ----@alias lsp.PrepareRenameResult lsp.Range|anonym44|anonym45 +---@alias lsp.PrepareRenameResult lsp.Range|lsp._anonym44.PrepareRenameResult|lsp._anonym45.PrepareRenameResult ---A document selector is the combination of one or many document filters. --- ----@sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**∕tsconfig.json' }]`; +---\@sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**∕tsconfig.json' }]`; --- ---The use of a string as a document filter is deprecated @since 3.16.0. ---@alias lsp.DocumentSelector lsp.DocumentFilter[] @@ -4000,7 +4691,7 @@ error('Cannot require a meta file') ---An event describing a change to a text document. If only a text is provided ---it is considered to be the full content of the document. ----@alias lsp.TextDocumentContentChangeEvent anonym46|anonym47 +---@alias lsp.TextDocumentContentChangeEvent lsp._anonym46.TextDocumentContentChangeEvent|lsp._anonym47.TextDocumentContentChangeEvent ---MarkedString can be used to render human readable text. It is either a markdown string ---or a code-block that provides a language and a code snippet. The language identifier @@ -4014,7 +4705,7 @@ error('Cannot require a meta file') --- ---Note that markdown strings will be sanitized - that means html will be escaped. ---@deprecated use MarkupContent instead. ----@alias lsp.MarkedString string|anonym48 +---@alias lsp.MarkedString string|lsp._anonym48.MarkedString ---A document filter describes a top level text document or ---a notebook cell document. @@ -4039,120 +4730,145 @@ error('Cannot require a meta file') ---- `*` 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 sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files) +---- `{}` to group sub patterns into an OR expression. (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`) --- ----@sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }` ----@sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }` +---\@sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }` +---\@sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }` --- ---@since 3.17.0 ----@alias lsp.TextDocumentFilter anonym49|anonym50|anonym51 +---@alias lsp.TextDocumentFilter lsp._anonym49.TextDocumentFilter|lsp._anonym50.TextDocumentFilter|lsp._anonym51.TextDocumentFilter ---A notebook document filter denotes a notebook document by ---different properties. The properties will be match ---against the notebook's URI (same as with documents) --- ---@since 3.17.0 ----@alias lsp.NotebookDocumentFilter anonym52|anonym53|anonym54 +---@alias lsp.NotebookDocumentFilter lsp._anonym52.NotebookDocumentFilter|lsp._anonym53.NotebookDocumentFilter|lsp._anonym54.NotebookDocumentFilter ---The glob pattern to watch relative to the base path. Glob patterns can have the following syntax: ---- `*` 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 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`) --- ---@since 3.17.0 ---@alias lsp.Pattern string ----@class anonym1 +---@class lsp._anonym1.serverInfo +--- ---The name of the server as defined by the server. ---@field name string +--- ---The server's version as defined by the server. ---@field version? string ----@class anonym3 +---@class lsp._anonym3.itemDefaults.editRange +--- ---@field insert lsp.Range +--- ---@field replace lsp.Range ----@class anonym2 +---@class lsp._anonym2.itemDefaults +--- ---A default commit character set. --- ---@since 3.17.0 ---@field commitCharacters? string[] +--- ---A default edit range. --- ---@since 3.17.0 ----@field editRange? lsp.Range|anonym3 +---@field editRange? lsp.Range|lsp._anonym3.itemDefaults.editRange +--- ---A default insert text format. --- ---@since 3.17.0 ---@field insertTextFormat? lsp.InsertTextFormat +--- ---A default insert text mode. --- ---@since 3.17.0 ---@field insertTextMode? lsp.InsertTextMode +--- ---A default data value. --- ---@since 3.17.0 ---@field data? lsp.LSPAny ----@class anonym4 +---@class lsp._anonym4.disabled +--- ---Human readable description of why the code action is currently disabled. --- ---This is displayed in the code actions UI. ---@field reason string ----@class anonym5 +---@class lsp._anonym5.location +--- ---@field uri lsp.DocumentUri ----@class anonym6 +---@class lsp._anonym6.range ----@class anonym7 +---@class lsp._anonym7.full +--- ---The server supports deltas for full documents. ---@field delta? boolean ----@class anonym9 +---@class lsp._anonym9.cells.structure +--- ---The change to the cell array. ---@field array lsp.NotebookCellArrayChange +--- ---Additional opened cell text documents. ---@field didOpen? lsp.TextDocumentItem[] +--- ---Additional closed cell text documents. ---@field didClose? lsp.TextDocumentIdentifier[] ----@class anonym10 +---@class lsp._anonym10.cells.textContent +--- ---@field document lsp.VersionedTextDocumentIdentifier +--- ---@field changes lsp.TextDocumentContentChangeEvent[] ----@class anonym8 +---@class lsp._anonym8.cells +--- ---Changes to the cell structure to add or ---remove cells. ----@field structure? anonym9 +---@field structure? lsp._anonym9.cells.structure +--- ---Changes to notebook cells properties like its ---kind, execution summary or metadata. ---@field data? lsp.NotebookCell[] +--- ---Changes to the text content of notebook cells. ----@field textContent? anonym10[] +---@field textContent? lsp._anonym10.cells.textContent[] ----@class anonym11 +---@class lsp._anonym11.clientInfo +--- ---The name of the client as defined by the client. ---@field name string +--- ---The client's version as defined by the client. ---@field version? string ----@class anonym12 +---@class lsp._anonym12.workspace +--- ---The server supports workspace folder. --- ---@since 3.6.0 ---@field workspaceFolders? lsp.WorkspaceFoldersServerCapabilities +--- ---The server is interested in notifications/requests for operations on files. --- ---@since 3.16.0 ---@field fileOperations? lsp.FileOperationOptions ----@class anonym13 +---@class lsp._anonym13.completionItem +--- ---The server has support for completion item label ---details (see also `CompletionItemLabelDetails`) when ---receiving a completion item in a resolve call. @@ -4160,43 +4876,53 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@field labelDetailsSupport? boolean ----@class anonym15 +---@class lsp._anonym15.notebookSelector.cells +--- ---@field language string ----@class anonym14 +---@class lsp._anonym14.notebookSelector +--- ---The notebook to be synced If a string ---value is provided it matches against the ---notebook type. '*' matches every notebook. ---@field notebook string|lsp.NotebookDocumentFilter +--- ---The cells of the matching notebook to be synced. ----@field cells? anonym15[] +---@field cells? lsp._anonym15.notebookSelector.cells[] ----@class anonym17 +---@class lsp._anonym17.notebookSelector.cells +--- ---@field language string ----@class anonym16 +---@class lsp._anonym16.notebookSelector +--- ---The notebook to be synced If a string ---value is provided it matches against the ---notebook type. '*' matches every notebook. ---@field notebook? string|lsp.NotebookDocumentFilter +--- ---The cells of the matching notebook to be synced. ----@field cells anonym17[] +---@field cells lsp._anonym17.notebookSelector.cells[] ----@class anonym18 +---@class lsp._anonym18.staleRequestSupport +--- ---The client will actively cancel the request. ---@field cancel boolean +--- ---The list of requests for which the client ---will retry the request if it receives a ---response with error code `ContentModified` ---@field retryOnContentModified string[] ----@class anonym19 +---@class lsp._anonym19.changeAnnotationSupport +--- ---Whether the client groups edits with equal labels into tree nodes, ---for instance all edits labelled with "Changes in Strings" would ---be a tree node. ---@field groupsOnLabel? boolean ----@class anonym20 +---@class lsp._anonym20.symbolKind +--- ---The symbol kind values the client supports. When this ---property exists the client also guarantees that it will ---handle values outside its set gracefully and falls back @@ -4207,27 +4933,33 @@ error('Cannot require a meta file') ---the initial version of the protocol. ---@field valueSet? lsp.SymbolKind[] ----@class anonym21 +---@class lsp._anonym21.tagSupport +--- ---The tags supported by the client. ---@field valueSet lsp.SymbolTag[] ----@class anonym22 +---@class lsp._anonym22.resolveSupport +--- ---The properties that a client can resolve lazily. Usually ---`location.range` ---@field properties string[] ----@class anonym24 +---@class lsp._anonym24.completionItem.tagSupport +--- ---The tags supported by the client. ---@field valueSet lsp.CompletionItemTag[] ----@class anonym25 +---@class lsp._anonym25.completionItem.resolveSupport +--- ---The properties that a client can resolve lazily. ---@field properties string[] ----@class anonym26 +---@class lsp._anonym26.completionItem.insertTextModeSupport +--- ---@field valueSet lsp.InsertTextMode[] ----@class anonym23 +---@class lsp._anonym23.completionItem +--- ---Client supports snippets as insert text. --- ---A snippet can define tab stops and placeholders with `$1`, `$2` @@ -4235,46 +4967,56 @@ error('Cannot require a meta file') ---the end of the snippet. Placeholders with equal identifiers are linked, ---that is typing in one will update others too. ---@field snippetSupport? boolean +--- ---Client supports commit characters on a completion item. ---@field commitCharactersSupport? boolean +--- ---Client supports the following content formats for the documentation ---property. The order describes the preferred format of the client. ---@field documentationFormat? lsp.MarkupKind[] +--- ---Client supports the deprecated property on a completion item. ---@field deprecatedSupport? boolean +--- ---Client supports the preselect property on a completion item. ---@field preselectSupport? boolean +--- ---Client supports the tag property on a completion item. Clients supporting ---tags have to handle unknown tags gracefully. Clients especially need to ---preserve unknown tags when sending a completion item back to the server in ---a resolve call. --- ---@since 3.15.0 ----@field tagSupport? anonym24 +---@field tagSupport? lsp._anonym24.completionItem.tagSupport +--- ---Client support insert replace edit to control different behavior if a ---completion item is inserted in the text or should replace text. --- ---@since 3.16.0 ---@field insertReplaceSupport? boolean +--- ---Indicates which properties a client can resolve lazily on a completion ---item. Before version 3.16.0 only the predefined properties `documentation` ---and `details` could be resolved lazily. --- ---@since 3.16.0 ----@field resolveSupport? anonym25 +---@field resolveSupport? lsp._anonym25.completionItem.resolveSupport +--- ---The client supports the `insertTextMode` property on ---a completion item to override the whitespace handling mode ---as defined by the client (see `insertTextMode`). --- ---@since 3.16.0 ----@field insertTextModeSupport? anonym26 +---@field insertTextModeSupport? lsp._anonym26.completionItem.insertTextModeSupport +--- ---The client has support for completion item label ---details (see also `CompletionItemLabelDetails`). --- ---@since 3.17.0 ---@field labelDetailsSupport? boolean ----@class anonym27 +---@class lsp._anonym27.completionItemKind +--- ---The completion item kind values the client supports. When this ---property exists the client also guarantees that it will ---handle values outside its set gracefully and falls back @@ -4285,7 +5027,8 @@ error('Cannot require a meta file') ---the initial version of the protocol. ---@field valueSet? lsp.CompletionItemKind[] ----@class anonym28 +---@class lsp._anonym28.completionList +--- ---The client supports the following itemDefaults on ---a completion list. --- @@ -4296,24 +5039,29 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@field itemDefaults? string[] ----@class anonym30 +---@class lsp._anonym30.signatureInformation.parameterInformation +--- ---The client supports processing label offsets instead of a ---simple label string. --- ---@since 3.14.0 ---@field labelOffsetSupport? boolean ----@class anonym29 +---@class lsp._anonym29.signatureInformation +--- ---Client supports the following content formats for the documentation ---property. The order describes the preferred format of the client. ---@field documentationFormat? lsp.MarkupKind[] +--- ---Client capabilities specific to parameter information. ----@field parameterInformation? anonym30 +---@field parameterInformation? lsp._anonym30.signatureInformation.parameterInformation +--- ---The client supports the `activeParameter` property on `SignatureInformation` ---literal. --- ---@since 3.16.0 ---@field activeParameterSupport? boolean +--- ---The client supports the `activeParameter` property on ---`SignatureInformation` being set to `null` to indicate that no ---parameter should be active. @@ -4321,7 +5069,8 @@ error('Cannot require a meta file') ---@since 3.18.0 ---@field noActiveParameterSupport? boolean ----@class anonym31 +---@class lsp._anonym31.symbolKind +--- ---The symbol kind values the client supports. When this ---property exists the client also guarantees that it will ---handle values outside its set gracefully and falls back @@ -4332,138 +5081,177 @@ error('Cannot require a meta file') ---the initial version of the protocol. ---@field valueSet? lsp.SymbolKind[] ----@class anonym32 +---@class lsp._anonym32.tagSupport +--- ---The tags supported by the client. ---@field valueSet lsp.SymbolTag[] ----@class anonym34 +---@class lsp._anonym34.codeActionLiteralSupport.codeActionKind +--- ---The code action kind values the client supports. When this ---property exists the client also guarantees that it will ---handle values outside its set gracefully and falls back ---to a default value when unknown. ---@field valueSet lsp.CodeActionKind[] ----@class anonym33 +---@class lsp._anonym33.codeActionLiteralSupport +--- ---The code action kind is support with the following value ---set. ----@field codeActionKind anonym34 +---@field codeActionKind lsp._anonym34.codeActionLiteralSupport.codeActionKind ----@class anonym35 +---@class lsp._anonym35.resolveSupport +--- ---The properties that a client can resolve lazily. ---@field properties string[] ----@class anonym36 +---@class lsp._anonym36.foldingRangeKind +--- ---The folding range kind values the client supports. When this ---property exists the client also guarantees that it will ---handle values outside its set gracefully and falls back ---to a default value when unknown. ---@field valueSet? lsp.FoldingRangeKind[] ----@class anonym37 +---@class lsp._anonym37.foldingRange +--- ---If set, the client signals that it supports setting collapsedText on ---folding ranges to display custom labels instead of the default text. --- ---@since 3.17.0 ---@field collapsedText? boolean ----@class anonym38 +---@class lsp._anonym38.tagSupport +--- ---The tags supported by the client. ---@field valueSet lsp.DiagnosticTag[] ----@class anonym40 +---@class lsp._anonym40.requests.range ----@class anonym41 +---@class lsp._anonym41.requests.full +--- ---The client will send the `textDocument/semanticTokens/full/delta` request if ---the server provides a corresponding handler. ---@field delta? boolean ----@class anonym39 +---@class lsp._anonym39.requests +--- ---The client will send the `textDocument/semanticTokens/range` request if ---the server provides a corresponding handler. ----@field range? boolean|anonym40 +---@field range? boolean|lsp._anonym40.requests.range +--- ---The client will send the `textDocument/semanticTokens/full` request if ---the server provides a corresponding handler. ----@field full? boolean|anonym41 +---@field full? boolean|lsp._anonym41.requests.full ----@class anonym42 +---@class lsp._anonym42.resolveSupport +--- ---The properties that a client can resolve lazily. ---@field properties string[] ----@class anonym43 +---@class lsp._anonym43.messageActionItem +--- ---Whether the client supports additional attributes which ---are preserved and send back to the server in the ---request's response. ---@field additionalPropertiesSupport? boolean ----@class anonym44 +---@class lsp._anonym44.PrepareRenameResult +--- ---@field range lsp.Range +--- ---@field placeholder string ----@class anonym45 +---@class lsp._anonym45.PrepareRenameResult +--- ---@field defaultBehavior boolean ----@class anonym46 +---@class lsp._anonym46.TextDocumentContentChangeEvent +--- ---The range of the document that changed. ---@field range lsp.Range +--- ---The optional length of the range that got replaced. --- ---@deprecated use range instead. ---@field rangeLength? uinteger +--- ---The new text for the provided range. ---@field text string ----@class anonym47 +---@class lsp._anonym47.TextDocumentContentChangeEvent +--- ---The new text of the whole document. ---@field text string ----@class anonym48 +---@class lsp._anonym48.MarkedString +--- ---@field language string +--- ---@field value string ----@class anonym49 +---@class lsp._anonym49.TextDocumentFilter +--- ---A language id, like `typescript`. ---@field language string +--- ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme? string ----A glob pattern, like **​/*.{ts,js}. See TextDocumentFilter for examples. +--- +---A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples. ---@field pattern? string ----@class anonym50 +---@class lsp._anonym50.TextDocumentFilter +--- ---A language id, like `typescript`. ---@field language? string +--- ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme string ----A glob pattern, like **​/*.{ts,js}. See TextDocumentFilter for examples. +--- +---A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples. ---@field pattern? string ----@class anonym51 +---@class lsp._anonym51.TextDocumentFilter +--- ---A language id, like `typescript`. ---@field language? string +--- ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme? string ----A glob pattern, like **​/*.{ts,js}. See TextDocumentFilter for examples. +--- +---A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples. ---@field pattern string ----@class anonym52 +---@class lsp._anonym52.NotebookDocumentFilter +--- ---The type of the enclosing notebook. ---@field notebookType string +--- ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme? string +--- ---A glob pattern. ---@field pattern? string ----@class anonym53 +---@class lsp._anonym53.NotebookDocumentFilter +--- ---The type of the enclosing notebook. ---@field notebookType? string +--- ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme string +--- ---A glob pattern. ---@field pattern? string ----@class anonym54 +---@class lsp._anonym54.NotebookDocumentFilter +--- ---The type of the enclosing notebook. ---@field notebookType? string +--- ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme? string +--- ---A glob pattern. ---@field pattern string -- cgit From e0eb4188bfabefac54dd7cdcfe57fbb6ddb724b5 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Wed, 27 Dec 2023 09:42:30 +0100 Subject: revert: "fix: correct versions in deprecation warnings" This reverts commit 5cb906e91cb56302d0737aa80e2d890dde452029. They were intentionally fast-tracked. - `parse_snippet()` because of limited scope, and given that it's kinda semi-broken (arbitrary formatting rules, not that useful for what it was used for) - `extract_completion_items()` doesn't work if we want to add the LSP completionlist capability - `text_document_completion_list_to_complete_items()` also doesn't work for completionlist --- runtime/lua/vim/lsp/util.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 90e2f28ef4..ba7ce3c2b6 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -553,7 +553,7 @@ end ---@return lsp.CompletionItem[] List of completion items ---@see https://microsoft.github.io/language-server-protocol/specification#textDocument_completion function M.extract_completion_items(result) - vim.deprecate('vim.lsp.util.extract_completion_items()', nil, '0.12') + vim.deprecate('vim.lsp.util.extract_completion_items()', nil, '0.11') if type(result) == 'table' and result.items then -- result is a `CompletionList` return result.items @@ -613,7 +613,7 @@ end ---@param input string unparsed snippet ---@return string parsed snippet function M.parse_snippet(input) - vim.deprecate('vim.lsp.util.parse_snippet()', nil, '0.12') + vim.deprecate('vim.lsp.util.parse_snippet()', nil, '0.11') local ok, parsed = pcall(function() return snippet.parse(input) end) @@ -635,7 +635,7 @@ end ---@return table[] items ---@see complete-items function M.text_document_completion_list_to_complete_items(result, prefix) - vim.deprecate('vim.lsp.util.text_document_completion_list_to_complete_items()', nil, '0.12') + vim.deprecate('vim.lsp.util.text_document_completion_list_to_complete_items()', nil, '0.11') return require('vim.lsp._completion')._lsp_to_complete_items(result, prefix) end -- cgit From 714b075197c02d27d5c05133759ae97bed279b50 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Thu, 28 Dec 2023 03:28:48 +0100 Subject: docs: small fixes (#26651) Co-authored-by: Gregory Anders Co-authored-by: WillLillis --- runtime/lua/vim/_defaults.lua | 2 +- runtime/lua/vim/_meta/api.lua | 1 - runtime/lua/vim/health.lua | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 0d756b8701..af962eea5d 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -194,7 +194,7 @@ if tty then --- already set by the user. --- --- @param option string Option name - --- @param value string Option value + --- @param value any Option value local function setoption(option, value) if vim.api.nvim_get_option_info2(option, {}).was_set then -- Don't do anything if option is already set diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index ba18a16488..d94cef481e 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1493,7 +1493,6 @@ function vim.api.nvim_open_term(buffer, opts) end --- ```lua --- vim.api.nvim_open_win(0, false, --- {relative='win', width=12, height=3, bufpos={100,10}}) ---- }) --- ``` --- --- @param buffer integer Buffer to display, or 0 for current buffer diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua index 6c96a703bb..23771d2807 100644 --- a/runtime/lua/vim/health.lua +++ b/runtime/lua/vim/health.lua @@ -251,7 +251,7 @@ local path2name = function(path) end local PATTERNS = { '/autoload/health/*.vim', '/lua/**/**/health.lua', '/lua/**/**/health/init.lua' } --- :checkhealth completion function used by ex_getln.c get_healthcheck_names() +-- :checkhealth completion function used by cmdexpand.c get_healthcheck_names() M._complete = function() local names = vim.tbl_flatten(vim.tbl_map(function(pattern) return vim.tbl_map(path2name, vim.api.nvim_get_runtime_file(pattern, true)) -- cgit From 53a3e6ac879d89039c69d3e44f46ed9bf857a9d9 Mon Sep 17 00:00:00 2001 From: xvzc <45588457+xvzc@users.noreply.github.com> Date: Thu, 28 Dec 2023 20:13:46 +0900 Subject: docs(eval): add parameter type for vim.fn.mode() (#26776) --- runtime/lua/vim/_meta/vimfn.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 59d9836688..02e794ce10 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -5829,8 +5829,9 @@ function vim.fn.mkdir(name, flags, prot) end --- the leading character(s). --- Also see |visualmode()|. --- +--- @param expr? any --- @return any -function vim.fn.mode() end +function vim.fn.mode(expr) end --- Convert a list of Vimscript objects to msgpack. Returned value is a --- |readfile()|-style list. When {type} contains "B", a |Blob| is -- cgit From d51b6157473c4830313b566116aa3ad38dc97412 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Wed, 13 Dec 2023 14:04:24 +0100 Subject: refactor: fix luals warnings --- runtime/lua/vim/_editor.lua | 29 +++++++---- runtime/lua/vim/_init_packages.lua | 1 + runtime/lua/vim/_watch.lua | 1 + runtime/lua/vim/diagnostic.lua | 1 + runtime/lua/vim/health.lua | 102 ++++++++++++++++++++++++++----------- runtime/lua/vim/iter.lua | 9 +++- runtime/lua/vim/loader.lua | 2 +- runtime/lua/vim/lsp.lua | 4 +- runtime/lua/vim/lsp/buf.lua | 2 +- runtime/lua/vim/shared.lua | 5 -- runtime/lua/vim/ui.lua | 2 +- 11 files changed, 108 insertions(+), 50 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 0b338fa86f..cde61697b6 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -156,10 +156,10 @@ function vim._os_proc_info(pid) elseif r.code ~= 0 then error('command failed: ' .. vim.fn.string(cmd)) end - local ppid = assert(vim.system({ 'ps', '-p', pid, '-o', 'ppid=' }):wait().stdout) + local ppid_string = assert(vim.system({ 'ps', '-p', pid, '-o', 'ppid=' }):wait().stdout) -- Remove trailing whitespace. name = vim.trim(name):gsub('^.*/', '') - ppid = tonumber(ppid) or -1 + local ppid = tonumber(ppid_string) or -1 return { name = name, pid = pid, @@ -533,20 +533,21 @@ function vim.region(bufnr, pos1, pos2, regtype, inclusive) local region = {} for l = pos1[1], pos2[1] do - local c1, c2 + local c1 --- @type number + local c2 --- @type number if regtype:byte() == 22 then -- block selection: take width from regtype c1 = pos1[2] - c2 = c1 + regtype:sub(2) + c2 = c1 + tonumber(regtype:sub(2)) -- and adjust for non-ASCII characters local bufline = vim.api.nvim_buf_get_lines(bufnr, l, l + 1, true)[1] local utflen = vim.str_utfindex(bufline, #bufline) if c1 <= utflen then - c1 = vim.str_byteindex(bufline, c1) + c1 = assert(tonumber(vim.str_byteindex(bufline, c1))) else c1 = #bufline + 1 end if c2 <= utflen then - c2 = vim.str_byteindex(bufline, c2) + c2 = assert(tonumber(vim.str_byteindex(bufline, c2))) else c2 = #bufline + 1 end @@ -576,7 +577,7 @@ end ---@return table timer luv timer object function vim.defer_fn(fn, timeout) vim.validate({ fn = { fn, 'c', true } }) - local timer = vim.uv.new_timer() + local timer = assert(vim.uv.new_timer()) timer:start( timeout, 0, @@ -601,6 +602,7 @@ end ---@param msg string Content of the notification to show to the user. ---@param level integer|nil One of the values from |vim.log.levels|. ---@param opts table|nil Optional parameters. Unused by default. +---@diagnostic disable-next-line: unused-local function vim.notify(msg, level, opts) -- luacheck: no unused args if level == vim.log.levels.ERROR then vim.api.nvim_err_writeln(msg) @@ -700,6 +702,8 @@ end --- --- 1. Can we get it to just return things in the global namespace with that name prefix --- 2. Can we get it to return things from global namespace even with `print(` in front. +--- +--- @param pat string function vim._expand_pat(pat, env) env = env or _G @@ -801,11 +805,13 @@ function vim._expand_pat(pat, env) return keys, #prefix_match_pat end +--- @param lua_string string vim._expand_pat_get_parts = function(lua_string) local parts = {} local accumulator, search_index = '', 1 - local in_brackets, bracket_end = false, -1 + local in_brackets = false + local bracket_end = -1 --- @type integer? local string_char = nil for idx = 1, #lua_string do local s = lua_string:sub(idx, idx) @@ -938,9 +944,12 @@ function vim.keycode(str) return vim.api.nvim_replace_termcodes(str, true, true, true) end +--- @param server_addr string +--- @param connect_error string function vim._cs_remote(rcid, server_addr, connect_error, args) + --- @return string local function connection_failure_errmsg(consequence) - local explanation + local explanation --- @type string if server_addr == '' then explanation = 'No server specified with --server' else @@ -983,7 +992,7 @@ function vim._cs_remote(rcid, server_addr, connect_error, args) local res = tostring(vim.rpcrequest(rcid, 'nvim_eval', args[2])) return { result = res, should_exit = true, tabbed = false } elseif subcmd ~= '' then - return { errmsg = 'Unknown option argument: ' .. args[1] } + return { errmsg = 'Unknown option argument: ' .. tostring(args[1]) } end if rcid == 0 then diff --git a/runtime/lua/vim/_init_packages.lua b/runtime/lua/vim/_init_packages.lua index f8710f7fd7..97d483333e 100644 --- a/runtime/lua/vim/_init_packages.lua +++ b/runtime/lua/vim/_init_packages.lua @@ -12,6 +12,7 @@ for s in (package.cpath .. ';'):gmatch('[^;]*;') do end end +--- @param name string function vim._load_package(name) local basename = name:gsub('%.', '/') local paths = { 'lua/' .. basename .. '.lua', 'lua/' .. basename .. '/init.lua' } diff --git a/runtime/lua/vim/_watch.lua b/runtime/lua/vim/_watch.lua index 43fce3bf7f..092781826f 100644 --- a/runtime/lua/vim/_watch.lua +++ b/runtime/lua/vim/_watch.lua @@ -51,6 +51,7 @@ function M.watch(path, opts, callback) local uvflags = opts and opts.uvflags or {} local handle, new_err = vim.uv.new_fs_event() assert(not new_err, new_err) + handle = assert(handle) local _, start_err = handle:start(path, uvflags, function(err, filename, events) assert(not err, err) local fullpath = path diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index a82a61eeb7..ad40723737 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -108,6 +108,7 @@ local function filter_by_severity(severity, diagnostics) severities[to_severity(s)] = true end + --- @param t table return vim.tbl_filter(function(t) return severities[t.severity] end, diagnostics) diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua index 23771d2807..55a451bf56 100644 --- a/runtime/lua/vim/health.lua +++ b/runtime/lua/vim/health.lua @@ -1,8 +1,8 @@ local M = {} -local s_output = {} +local s_output = {} ---@type string[] --- Returns the fold text of the current healthcheck section +--- Returns the fold text of the current healthcheck section function M.foldtext() local foldtext = vim.fn.foldtext() @@ -36,12 +36,13 @@ function M.foldtext() return vim.b.failedchecks[foldtext] and '+WE' .. foldtext:sub(4) or foldtext end --- From a path return a list [{name}, {func}, {type}] representing a healthcheck +--- @param path string path to search for the healthcheck +--- @return string[] { name, func, type } representing a healthcheck local function filepath_to_healthcheck(path) path = vim.fs.normalize(path) - local name - local func - local filetype + local name --- @type string + local func --- @type string + local filetype --- @type string if path:find('vim$') then name = vim.fs.basename(path):gsub('%.vim$', '') func = 'health#' .. name .. '#check' @@ -50,10 +51,10 @@ local function filepath_to_healthcheck(path) local subpath = path:gsub('.*lua/', '') if vim.fs.basename(subpath) == 'health.lua' then -- */health.lua - name = vim.fs.dirname(subpath) + name = assert(vim.fs.dirname(subpath)) else -- */health/init.lua - name = vim.fs.dirname(vim.fs.dirname(subpath)) + name = assert(vim.fs.dirname(assert(vim.fs.dirname(subpath)))) end name = name:gsub('/', '.') @@ -63,11 +64,12 @@ local function filepath_to_healthcheck(path) return { name, func, filetype } end --- Returns { {name, func, type}, ... } representing healthchecks +--- @param plugin_names string +--- @return table { {name, func, type}, ... } representing healthchecks local function get_healthcheck_list(plugin_names) - local healthchecks = {} - plugin_names = vim.split(plugin_names, ' ') - for _, p in pairs(plugin_names) do + local healthchecks = {} --- @type table + local plugin_names_list = vim.split(plugin_names, ' ') + for _, p in pairs(plugin_names_list) do -- support vim/lsp/health{/init/}.lua as :checkhealth vim.lsp p = p:gsub('%.', '/') @@ -83,7 +85,7 @@ local function get_healthcheck_list(plugin_names) if vim.tbl_count(paths) == 0 then healthchecks[#healthchecks + 1] = { p, '', '' } -- healthcheck not found else - local unique_paths = {} + local unique_paths = {} --- @type table for _, v in pairs(paths) do unique_paths[v] = true end @@ -100,10 +102,11 @@ local function get_healthcheck_list(plugin_names) return healthchecks end --- Returns {name: [func, type], ..} representing healthchecks +--- @param plugin_names string +--- @return table {name: [func, type], ..} representing healthchecks local function get_healthcheck(plugin_names) local health_list = get_healthcheck_list(plugin_names) - local healthchecks = {} + local healthchecks = {} --- @type table for _, c in pairs(health_list) do if c[1] ~= 'vim' then healthchecks[c[1]] = { c[2], c[3] } @@ -113,7 +116,11 @@ local function get_healthcheck(plugin_names) return healthchecks end --- Indents lines *except* line 1 of a string if it contains newlines. +--- Indents lines *except* line 1 of a string if it contains newlines. +--- +--- @param s string +--- @param columns integer +--- @return string local function indent_after_line1(s, columns) local lines = vim.split(s, '\n') local indent = string.rep(' ', columns) @@ -123,13 +130,20 @@ local function indent_after_line1(s, columns) return table.concat(lines, '\n') end --- Changes ':h clipboard' to ':help |clipboard|'. +--- Changes ':h clipboard' to ':help |clipboard|'. +--- +--- @param s string +--- @return string local function help_to_link(s) return vim.fn.substitute(s, [[\v:h%[elp] ([^|][^"\r\n ]+)]], [[:help |\1|]], [[g]]) end --- Format a message for a specific report item. --- Variable args: Optional advice (string or list) +--- Format a message for a specific report item. +--- +--- @param status string +--- @param msg string +--- @param ... string|string[] Optional advice +--- @return string local function format_report_message(status, msg, ...) local output = '- ' .. status if status ~= '' then @@ -159,42 +173,54 @@ local function format_report_message(status, msg, ...) return help_to_link(output) end +--- @param output string local function collect_output(output) vim.list_extend(s_output, vim.split(output, '\n')) end --- Starts a new report. +--- Starts a new report. +--- +--- @param name string function M.start(name) local input = string.format('\n%s ~', name) collect_output(input) end --- Reports a message in the current section. +--- Reports a message in the current section. +--- +--- @param msg string function M.info(msg) local input = format_report_message('', msg) collect_output(input) end --- Reports a successful healthcheck. +--- Reports a successful healthcheck. +--- +--- @param msg string function M.ok(msg) local input = format_report_message('OK', msg) collect_output(input) end --- Reports a health warning. --- ...: Optional advice (string or table) +--- Reports a health warning. +--- +--- @param msg string +--- @param ... string|string[] Optional advice function M.warn(msg, ...) local input = format_report_message('WARNING', msg, ...) collect_output(input) end --- Reports a failed healthcheck. --- ...: Optional advice (string or table) +--- Reports a failed healthcheck. +--- +--- @param msg string +--- @param ... string|string[] Optional advice function M.error(msg, ...) local input = format_report_message('ERROR', msg, ...) collect_output(input) end +--- @param type string local function deprecate(type) local before = string.format('vim.health.report_%s()', type) local after = string.format('vim.health.%s()', type) @@ -206,22 +232,36 @@ local function deprecate(type) vim.print('Running healthchecks...') end +--- @deprecated +--- @param name string function M.report_start(name) deprecate('start') M.start(name) end + +--- @deprecated +--- @param msg string function M.report_info(msg) deprecate('info') M.info(msg) end + +--- @deprecated +--- @param msg string function M.report_ok(msg) deprecate('ok') M.ok(msg) end + +--- @deprecated +--- @param msg string function M.report_warn(msg, ...) deprecate('warn') M.warn(msg, ...) end + +--- @deprecated +--- @param msg string function M.report_error(msg, ...) deprecate('error') M.error(msg, ...) @@ -251,7 +291,7 @@ local path2name = function(path) end local PATTERNS = { '/autoload/health/*.vim', '/lua/**/**/health.lua', '/lua/**/**/health/init.lua' } --- :checkhealth completion function used by cmdexpand.c get_healthcheck_names() +--- :checkhealth completion function used by cmdexpand.c get_healthcheck_names() M._complete = function() local names = vim.tbl_flatten(vim.tbl_map(function(pattern) return vim.tbl_map(path2name, vim.api.nvim_get_runtime_file(pattern, true)) @@ -270,6 +310,9 @@ end --- Runs all discovered healthchecks if plugin_names is empty. --- --- @param mods string command modifiers that affect splitting a window. +--- @param plugin_names string glob of plugin names, split on whitespace. For example, using +--- `:checkhealth vim.* nvim` will healthcheck `vim.lsp`, `vim.treesitter` +--- and `nvim` modules. function M._check(mods, plugin_names) local healthchecks = plugin_names == '' and get_healthcheck('*') or get_healthcheck(plugin_names) @@ -289,7 +332,8 @@ function M._check(mods, plugin_names) vim.cmd.file('health://') vim.cmd.setfiletype('checkhealth') - if healthchecks == nil or next(healthchecks) == nil then + -- This should only happen when doing `:checkhealth vim` + if next(healthchecks) == nil then vim.fn.setline(1, 'ERROR: No healthchecks found.') return end @@ -325,7 +369,7 @@ function M._check(mods, plugin_names) local header = { string.rep('=', 78), name .. ': ' .. func, '' } -- remove empty line after header from report_start if s_output[1] == '' then - local tmp = {} + local tmp = {} ---@type string[] for i = 2, #s_output do tmp[#tmp + 1] = s_output[i] end diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index 8e602c406a..b658dde099 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -432,6 +432,7 @@ end --- ``` --- ---@return any +---@diagnostic disable-next-line: unused-local function Iter.next(self) -- luacheck: no unused args -- This function is provided by the source iterator in Iter.new. This definition exists only for -- the docstring @@ -489,6 +490,7 @@ end --- ``` --- ---@return any +---@diagnostic disable-next-line: unused-local function Iter.peek(self) -- luacheck: no unused args error('peek() requires a list-like table') end @@ -568,12 +570,13 @@ end ---@see Iter.find --- ---@return any +---@diagnostic disable-next-line: unused-local function Iter.rfind(self, f) -- luacheck: no unused args error('rfind() requires a list-like table') end ---@private -function ListIter.rfind(self, f) -- luacheck: no unused args +function ListIter.rfind(self, f) if type(f) ~= 'function' then local val = f f = function(v) @@ -640,6 +643,7 @@ end --- ``` --- ---@return any +---@diagnostic disable-next-line: unused-local function Iter.nextback(self) -- luacheck: no unused args error('nextback() requires a list-like table') end @@ -669,6 +673,7 @@ end --- ``` --- ---@return any +---@diagnostic disable-next-line: unused-local function Iter.peekback(self) -- luacheck: no unused args error('peekback() requires a list-like table') end @@ -725,6 +730,7 @@ end --- ---@param n number Number of values to skip. ---@return Iter +---@diagnostic disable-next-line: unused-local function Iter.skipback(self, n) -- luacheck: no unused args error('skipback() requires a list-like table') return self @@ -791,6 +797,7 @@ end ---@param first number ---@param last number ---@return Iter +---@diagnostic disable-next-line: unused-local function Iter.slice(self, first, last) -- luacheck: no unused args error('slice() requires a list-like table') return self diff --git a/runtime/lua/vim/loader.lua b/runtime/lua/vim/loader.lua index ee01111337..b77251cf7e 100644 --- a/runtime/lua/vim/loader.lua +++ b/runtime/lua/vim/loader.lua @@ -1,5 +1,5 @@ local uv = vim.uv -local uri_encode = vim.uri_encode +local uri_encode = vim.uri_encode --- @type function --- @type (fun(modename: string): fun()|string)[] local loaders = package.loaders diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 1310239a5b..3105413b53 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -329,11 +329,11 @@ end ---@param fn (T) Function to run ---@return T local function once(fn) - local value --- @type any + local value --- @type function local ran = false return function(...) if not ran then - value = fn(...) + value = fn(...) --- @type function ran = true end return value diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 051b9d4550..d67b2ac8ea 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -46,7 +46,7 @@ function M.hover() end local function request_with_options(name, params, options) - local req_handler + local req_handler --- @type function? if options then req_handler = function(err, result, ctx, config) local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 9542d93789..bbbc888727 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -617,11 +617,6 @@ function vim.tbl_islist(t) local num_elem = vim.tbl_count(t) if num_elem == 0 then - -- TODO(bfredl): in the future, we will always be inside nvim - -- then this check can be deleted. - if vim._empty_dict_mt == nil then - return nil - end return getmetatable(t) ~= vim._empty_dict_mt else for i = 1, num_elem do diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua index b6ddf337ce..25ced18daf 100644 --- a/runtime/lua/vim/ui.lua +++ b/runtime/lua/vim/ui.lua @@ -133,7 +133,7 @@ function M.open(path) path = vim.fn.expand(path) end - local cmd + local cmd --- @type string[] if vim.fn.has('mac') == 1 then cmd = { 'open', path } -- cgit From 6fa0f303d7f0823bfc5ba6cc7b4e7a7cd76143ac Mon Sep 17 00:00:00 2001 From: altermo Date: Sun, 31 Dec 2023 14:08:16 +0100 Subject: fix(builtin): parameter mismatch between winsaveview and winrestview --- runtime/lua/vim/_meta/builtin_types.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/builtin_types.lua b/runtime/lua/vim/_meta/builtin_types.lua index ef0452c649..e74cf86173 100644 --- a/runtime/lua/vim/_meta/builtin_types.lua +++ b/runtime/lua/vim/_meta/builtin_types.lua @@ -118,7 +118,7 @@ --- @field topfill? integer --- @field topline? integer ---- @class vim.fn.winsaveview.ret +--- @class vim.fn.winsaveview.ret: vim.fn.winrestview.dict --- @field col integer --- @field coladd integer --- @field curswant integer -- cgit From 3faace199583f3a36470b717ce3e386e476f3a30 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Thu, 7 Dec 2023 21:01:50 +0900 Subject: docs: clarify on_bytes arguments based on extmark_splice doc --- runtime/lua/vim/_meta/api.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index d94cef481e..c0dfa7635b 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -173,11 +173,15 @@ function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start --- • start column of the changed text --- • byte offset of the changed text (from the start of --- the buffer) ---- • old end row of the changed text ---- • old end column of the changed text +--- • old end row of the changed text (offset from start +--- row) +--- • old end column of the changed text (if old end row +--- = 0, offset from start column) --- • old end byte length of the changed text ---- • new end row of the changed text ---- • new end column of the changed text +--- • new end row of the changed text (offset from start +--- row) +--- • new end column of the changed text (if new end row +--- = 0, offset from start column) --- • new end byte length of the changed text --- --- • on_changedtick: Lua callback invoked on changedtick -- cgit From 164f1ea06d17e935f41e178e46bb05bbb676af20 Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Mon, 10 Apr 2023 16:48:58 -0600 Subject: refactor(health): refactor provider healthchecks * Prefer pure Lua functions over vim.fn * Split up provider healthchecks into separate modules to help manage complexity --- runtime/lua/vim/health.lua | 115 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua index 55a451bf56..d9265f6bd6 100644 --- a/runtime/lua/vim/health.lua +++ b/runtime/lua/vim/health.lua @@ -267,6 +267,114 @@ function M.report_error(msg, ...) M.error(msg, ...) end +function M.provider_disabled(provider) + local loaded_var = 'loaded_' .. provider .. '_provider' + local v = vim.g[loaded_var] + if v == 0 then + M.info('Disabled (' .. loaded_var .. '=' .. v .. ').') + return true + end + return false +end + +-- Handler for s:system() function. +local function system_handler(self, _, data, event) + if event == 'stderr' then + if self.add_stderr_to_output then + self.output = self.output .. table.concat(data, '') + else + self.stderr = self.stderr .. table.concat(data, '') + end + elseif event == 'stdout' then + self.output = self.output .. table.concat(data, '') + end +end + +-- Attempts to construct a shell command from an args list. +-- Only for display, to help users debug a failed command. +local function shellify(cmd) + if type(cmd) ~= 'table' then + return cmd + end + local escaped = {} + for i, v in ipairs(cmd) do + if v:match('[^A-Za-z_/.-]') then + escaped[i] = vim.fn.shellescape(v) + else + escaped[i] = v + end + end + return table.concat(escaped, ' ') +end + +function M.cmd_ok(cmd) + local out = vim.fn.system(cmd) + return vim.v.shell_error == 0, out +end + +--- Run a system command and timeout after 30 seconds. +--- +--- @param cmd table List of command arguments to execute +--- @param args ?table Optional arguments: +--- - stdin (string): Data to write to the job's stdin +--- - stderr (boolean): Append stderr to stdout +--- - ignore_error (boolean): If true, ignore error output +--- - timeout (number): Number of seconds to wait before timing out (default 30) +function M.system(cmd, args) + args = args or {} + local stdin = args.stdin or '' + local stderr = vim.F.if_nil(args.stderr, false) + local ignore_error = vim.F.if_nil(args.ignore_error, false) + + local shell_error_code = 0 + local opts = { + add_stderr_to_output = stderr, + output = '', + stderr = '', + on_stdout = system_handler, + on_stderr = system_handler, + on_exit = function(_, data) + shell_error_code = data + end, + } + local jobid = vim.fn.jobstart(cmd, opts) + + if jobid < 1 then + local message = + string.format('Command error (job=%d): %s (in %s)', jobid, shellify(cmd), vim.loop.cwd()) + error(message) + return opts.output, 1 + end + + if stdin:find('^%s$') then + vim.fn.chansend(jobid, stdin) + end + + local res = vim.fn.jobwait({ jobid }, vim.F.if_nil(args.timeout, 30) * 1000) + if res[1] == -1 then + error('Command timed out: ' .. shellify(cmd)) + vim.fn.jobstop(jobid) + elseif shell_error_code ~= 0 and not ignore_error then + local emsg = string.format( + 'Command error (job=%d, exit code %d): %s (in %s)', + jobid, + shell_error_code, + shellify(cmd), + vim.loop.cwd() + ) + if opts.output:find('%S') then + emsg = string.format('%s\noutput: %s', emsg, opts.output) + end + if opts.stderr:find('%S') then + emsg = string.format('%s\nstderr: %s', emsg, opts.stderr) + end + error(emsg) + end + + -- return opts.output + return vim.trim(vim.fn.system(cmd)), shell_error_code +end + local path2name = function(path) if path:match('%.lua$') then -- Lua: transform "../lua/vim/lsp/health.lua" into "vim.lsp" @@ -389,4 +497,11 @@ function M._check(mods, plugin_names) vim.print('') end +local fn_bool = function(key) + return function(...) + return vim.fn[key](...) == 1 + end +end +M.executable = fn_bool('executable') + return M -- cgit From 4ee656e4f35766bef4e27c5afbfa8e3d8d74a76c Mon Sep 17 00:00:00 2001 From: Evgeni Chasnovski Date: Mon, 1 Jan 2024 23:03:50 +0200 Subject: feature(diagnostic): add `vim.diagnostic.count()` (#26807) feat(diagnostic): add `vim.diagnostic.count()` Problem: Getting diagnostic count based on the output of `vim.diagnostic.get()` might become costly as number of diagnostic entries grows. This is because it returns a copy of diagnostic cache entries (so as to not allow users to change them in place). Getting information about diagnostic count is frequently used in statusline, so it is important to be as fast as reasonbly possible. Solution: Add `vim.diagnostic.count()` which computes severity counts without making copies. --- runtime/lua/vim/diagnostic.lua | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index ad40723737..a447463dff 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -363,7 +363,6 @@ local function get_diagnostics(bufnr, opts, clamp) local function add(b, d) if not opts.lnum or d.lnum == opts.lnum then - d = vim.deepcopy(d) if clamp and api.nvim_buf_is_loaded(b) then local line_count = buf_line_count[b] - 1 if @@ -374,6 +373,7 @@ local function get_diagnostics(bufnr, opts, clamp) or d.col < 0 or d.end_col < 0 then + d = vim.deepcopy(d) d.lnum = math.max(math.min(d.lnum, line_count), 0) d.end_lnum = math.max(math.min(d.end_lnum, line_count), 0) d.col = math.max(d.col, 0) @@ -756,7 +756,31 @@ function M.get(bufnr, opts) opts = { opts, 't', true }, }) - return get_diagnostics(bufnr, opts, false) + return vim.deepcopy(get_diagnostics(bufnr, opts, false)) +end + +--- Get current diagnostics count. +--- +---@param bufnr integer|nil Buffer number to get diagnostics from. Use 0 for +--- current buffer or nil for all buffers. +---@param opts table|nil A table with the following keys: +--- - namespace: (number) Limit diagnostics to the given namespace. +--- - lnum: (number) Limit diagnostics to the given line number. +--- - severity: See |diagnostic-severity|. +---@return table A table with actually present severity values as keys (see |diagnostic-severity|) and integer counts as values. +function M.count(bufnr, opts) + vim.validate({ + bufnr = { bufnr, 'n', true }, + opts = { opts, 't', true }, + }) + + local diagnostics = get_diagnostics(bufnr, opts, false) + local count = {} + for i = 1, #diagnostics do + local severity = diagnostics[i].severity + count[severity] = (count[severity] or 0) + 1 + end + return count end --- Get the previous diagnostic closest to the cursor position. -- cgit From 3f788e73b34521f093846d362bf51e68bc9a3827 Mon Sep 17 00:00:00 2001 From: TheLeoP <53507599+TheLeoP@users.noreply.github.com> Date: Tue, 2 Jan 2024 04:08:36 -0500 Subject: feat(lsp): support connect via named pipes/unix domain sockets (#26032) Closes https://github.com/neovim/neovim/issues/26031 Co-authored-by: Mathias Fussenegger --- runtime/lua/vim/lsp/rpc.lua | 253 ++++++++++++++++++++++++++++++++------------ 1 file changed, 186 insertions(+), 67 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 61ad1e479c..b0d98829a6 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -5,8 +5,31 @@ local validate, schedule, schedule_wrap = vim.validate, vim.schedule, vim.schedu local is_win = uv.os_uname().version:find('Windows') +---@alias vim.lsp.rpc.Dispatcher fun(method: string, params: table):nil, vim.lsp.rpc.Error? +---@alias vim.lsp.rpc.on_error fun(code: integer, ...: any) +---@alias vim.lsp.rpc.on_exit fun(code: integer, signal: integer) + +---@class vim.lsp.rpc.Dispatchers +---@field notification vim.lsp.rpc.Dispatcher +---@field server_request vim.lsp.rpc.Dispatcher +---@field on_exit vim.lsp.rpc.on_error +---@field on_error vim.lsp.rpc.on_exit + +---@class vim.lsp.rpc.PublicClient +---@field request fun(method: string, params?: table, callback: fun(err: lsp.ResponseError | nil, result: any), notify_reply_callback:function?) +---@field notify fun(method: string, params: any) +---@field is_closing fun(): boolean +---@field terminate fun(): nil + +---@class vim.lsp.rpc.Client +---@field message_index integer +---@field message_callbacks table dict of message_id to callback +---@field notify_reply_callbacks table dict of message_id to callback +---@field transport vim.lsp.rpc.Transport +---@field dispatchers vim.lsp.rpc.Dispatchers + --- Checks whether a given path exists and is a directory. ----@param filename (string) path to check +---@param filename string path to check ---@return boolean local function is_dir(filename) local stat = uv.fs_stat(filename) @@ -15,14 +38,14 @@ end --- Embeds the given string into a table and correctly computes `Content-Length`. --- ----@param encoded_message (string) ----@return string containing encoded message and `Content-Length` attribute -local function format_message_with_content_length(encoded_message) +---@param message string +---@return string message with `Content-Length` attribute +local function format_message_with_content_length(message) return table.concat({ 'Content-Length: ', - tostring(#encoded_message), + tostring(#message), '\r\n\r\n', - encoded_message, + message, }) end @@ -44,13 +67,17 @@ local function log_debug(...) end end +---@class vim.lsp.rpc.Headers: {string: any} +---@field content_length integer + --- Parses an LSP Message's header --- ----@param header string: The header to parse. ----@return table # parsed headers +---@param header string The header to parse. +---@return vim.lsp.rpc.Headers#parsed headers local function parse_headers(header) assert(type(header) == 'string', 'header must be a string') - local headers = {} --- @type table + --- @type vim.lsp.rpc.Headers + local headers = {} for line in vim.gsplit(header, '\r\n', { plain = true }) do if line == '' then break @@ -92,15 +119,25 @@ local function request_parser_loop() -- be searching for. -- TODO(ashkan) I'd like to remove this, but it seems permanent :( local buffer_start = buffer:find(header_start_pattern) + if not buffer_start then + error( + string.format( + "Headers were expected, a different response was received. The server response was '%s'.", + buffer + ) + ) + end local headers = parse_headers(buffer:sub(buffer_start, start - 1)) local content_length = headers.content_length -- Use table instead of just string to buffer the message. It prevents -- a ton of strings allocating. -- ref. http://www.lua.org/pil/11.6.html + ---@type string[] local body_chunks = { buffer:sub(finish + 1) } local body_length = #body_chunks[1] -- Keep waiting for data until we have enough. while body_length < content_length do + ---@type string local chunk = coroutine.yield() or error('Expected more data for the body. The server may have died.') -- TODO hmm. table.insert(body_chunks, chunk) @@ -148,8 +185,8 @@ M.client_errors = vim.tbl_add_reverse_lookup(M.client_errors) --- Constructs an error message from an LSP error object. --- ----@param err (table) The error object ----@returns (string) The formatted error message +---@param err table The error object +---@return string#The formatted error message function M.format_rpc_error(err) validate({ err = { err, 't' }, @@ -176,11 +213,17 @@ function M.format_rpc_error(err) return table.concat(message_parts, ' ') end +---@class vim.lsp.rpc.Error +---@field code integer RPC error code defined by JSON RPC, see `vim.lsp.protocol.ErrorCodes` +---@field message? string arbitrary message to send to server +---@field data? any arbitrary data to send to server + --- Creates an RPC response object/table. --- ----@param code integer RPC error code defined in `vim.lsp.protocol.ErrorCodes` ----@param message string|nil arbitrary message to send to server ----@param data any|nil arbitrary data to send to server +---@param code integer RPC error code defined by JSON RPC +---@param message? string arbitrary message to send to server +---@param data? any arbitrary data to send to server +---@return vim.lsp.rpc.Error function M.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') @@ -204,7 +247,7 @@ local default_dispatchers = { --- Default dispatcher for notifications sent to an LSP server. --- ---@param method (string) The invoked LSP method - ---@param params (table): Parameters for the invoked LSP method + ---@param params (table) Parameters for the invoked LSP method notification = function(method, params) log_debug('notification', method, params) end, @@ -212,9 +255,9 @@ local default_dispatchers = { --- Default dispatcher for requests sent to an LSP server. --- ---@param method (string) The invoked LSP method - ---@param params (table): Parameters for the invoked LSP method + ---@param params (table) Parameters for the invoked LSP method ---@return nil - ---@return table, `vim.lsp.protocol.ErrorCodes.MethodNotFound` + ---@return vim.lsp.rpc.Error#`vim.lsp.protocol.ErrorCodes.MethodNotFound` server_request = function(method, params) log_debug('server_request', method, params) return nil, M.rpc_response_error(protocol.ErrorCodes.MethodNotFound) @@ -222,8 +265,8 @@ local default_dispatchers = { --- Default dispatcher for when a client exits. --- - ---@param code (integer): Exit code - ---@param signal (integer): Number describing the signal used to terminate (if + ---@param code (integer) Exit code + ---@param signal (integer) Number describing the signal used to terminate (if ---any) on_exit = function(code, signal) log_info('client_exit', { code = code, signal = signal }) @@ -231,17 +274,19 @@ local default_dispatchers = { --- Default dispatcher for client errors. --- - ---@param code (integer): Error code - ---@param err (any): Details about the error + ---@param code (integer) Error code + ---@param err (any) Details about the error ---any) on_error = function(code, err) log_error('client_error:', M.client_errors[code], err) end, } +---@cast default_dispatchers vim.lsp.rpc.Dispatchers + ---@private function M.create_read_loop(handle_body, on_no_chunk, on_error) - local parse_chunk = coroutine.wrap(request_parser_loop) + local parse_chunk = coroutine.wrap(request_parser_loop) --[[@as fun(chunk: string?): vim.lsp.rpc.Headers?, string?]] parse_chunk() return function(err, chunk) if err then @@ -268,14 +313,7 @@ function M.create_read_loop(handle_body, on_no_chunk, on_error) end end ----@class RpcClient ----@field message_index integer ----@field message_callbacks table ----@field notify_reply_callbacks table ----@field transport table ----@field dispatchers table - ----@class RpcClient +---@class vim.lsp.rpc.Client local Client = {} ---@private @@ -284,15 +322,18 @@ function Client:encode_and_send(payload) if self.transport.is_closing() then return false end - local encoded = vim.json.encode(payload) - self.transport.write(format_message_with_content_length(encoded)) + local jsonstr = assert( + vim.json.encode(payload), + string.format("Couldn't encode payload '%s'", vim.inspect(payload)) + ) + self.transport.write(format_message_with_content_length(jsonstr)) return true end ---@package --- Sends a notification to the LSP server. ----@param method (string) The invoked LSP method ----@param params (any): Parameters for the invoked LSP method +---@param method string The invoked LSP method +---@param params any Parameters for the invoked LSP method ---@return boolean `true` if notification could be sent, `false` if not function Client:notify(method, params) return self:encode_and_send({ @@ -316,10 +357,10 @@ end ---@package --- Sends a request to the LSP server and runs {callback} upon response. --- ----@param method (string) The invoked LSP method ----@param params (table|nil) Parameters for the invoked LSP method ----@param callback fun(err: lsp.ResponseError|nil, result: any) Callback to invoke ----@param notify_reply_callback (function|nil) Callback to invoke as soon as a request is no longer pending +---@param method string The invoked LSP method +---@param params? table Parameters for the invoked LSP method +---@param callback fun(err?: lsp.ResponseError, result: any) Callback to invoke +---@param notify_reply_callback? function Callback to invoke as soon as a request is no longer pending ---@return boolean success, integer|nil request_id true, request_id if request could be sent, `false` if not function Client:request(method, params, callback, notify_reply_callback) validate({ @@ -352,6 +393,8 @@ function Client:request(method, params, callback, notify_reply_callback) end ---@package +---@param errkind integer +---@param ... any function Client:on_error(errkind, ...) assert(M.client_errors[errkind]) -- TODO what to do if this fails? @@ -359,6 +402,13 @@ function Client:on_error(errkind, ...) end ---@private +---@param errkind integer +---@param status boolean +---@param head any +---@param ... any +---@return boolean status +---@return any head +---@return any|nil ... function Client:pcall_handler(errkind, status, head, ...) if not status then self:on_error(errkind, head, ...) @@ -368,6 +418,12 @@ function Client:pcall_handler(errkind, status, head, ...) end ---@private +---@param errkind integer +---@param fn function +---@param ... any +---@return boolean status +---@return any head +---@return any|nil ... function Client:try_call(errkind, fn, ...) return self:pcall_handler(errkind, pcall(fn, ...)) end @@ -386,7 +442,7 @@ function Client:handle_body(body) log_debug('rpc.receive', decoded) if type(decoded.method) == 'string' and decoded.id then - local err --- @type table? + local err --- @type vim.lsp.rpc.Error? -- Schedule here so that the users functions don't trigger an error and -- we can still use the result. schedule(function() @@ -412,6 +468,7 @@ function Client:handle_body(body) ) end if err then + ---@cast err vim.lsp.rpc.Error assert( type(err) == 'table', 'err must be a table. Use rpc_response_error to help format errors.' @@ -504,7 +561,14 @@ function Client:handle_body(body) end end ----@return RpcClient +---@class vim.lsp.rpc.Transport +---@field write fun(msg: string): nil +---@field is_closing fun(): boolean|nil +---@field terminate fun(): nil + +---@param dispatchers vim.lsp.rpc.Dispatchers +---@param transport vim.lsp.rpc.Transport +---@return vim.lsp.rpc.Client local function new_client(dispatchers, transport) local state = { message_index = 0, @@ -516,14 +580,8 @@ local function new_client(dispatchers, transport) return setmetatable(state, { __index = Client }) end ---- @class RpcClientPublic ---- @field is_closing fun(): boolean ---- @field terminate fun() ---- @field request fun(method: string, params: table?, callback: function, notify_reply_callbacks?: function) ---- @field notify fun(methid: string, params: table?): boolean - ----@param client RpcClient ----@return RpcClientPublic +---@param client vim.lsp.rpc.Client +---@return vim.lsp.rpc.PublicClient local function public_client(client) local result = {} @@ -540,9 +598,9 @@ local function public_client(client) --- Sends a request to the LSP server and runs {callback} upon response. --- ---@param method (string) The invoked LSP method - ---@param params (table|nil) Parameters for the invoked LSP method + ---@param params (table?) Parameters for the invoked LSP method ---@param callback fun(err: lsp.ResponseError | nil, result: any) Callback to invoke - ---@param notify_reply_callback (function|nil) Callback to invoke as soon as a request is no longer pending + ---@param notify_reply_callback (function?) Callback to invoke as soon as a request is no longer pending ---@return boolean success, integer|nil request_id true, message_id if request could be sent, `false` if not function result.request(method, params, callback, notify_reply_callback) return client:request(method, params, callback, notify_reply_callback) @@ -550,7 +608,7 @@ local function public_client(client) --- Sends a notification to the LSP server. ---@param method (string) The invoked LSP method - ---@param params (table|nil): Parameters for the invoked LSP method + ---@param params (table?) Parameters for the invoked LSP method ---@return boolean `true` if notification could be sent, `false` if not function result.notify(method, params) return client:notify(method, params) @@ -559,13 +617,15 @@ local function public_client(client) return result end ---- @param dispatchers vim.rpc.Dispatchers? ---- @return vim.rpc.Dispatchers +---@param dispatchers? vim.lsp.rpc.Dispatchers +---@return vim.lsp.rpc.Dispatchers local function merge_dispatchers(dispatchers) if dispatchers then local user_dispatchers = dispatchers dispatchers = {} for dispatch_name, default_dispatch in pairs(default_dispatchers) do + ---@cast dispatch_name string + ---@cast default_dispatch function local user_dispatcher = user_dispatchers[dispatch_name] --- @type function if user_dispatcher then if type(user_dispatcher) ~= 'function' then @@ -593,9 +653,9 @@ end --- Create a LSP RPC client factory that connects via TCP to the given host --- and port --- ----@param host string ----@param port integer ----@return function +---@param host string host to connect to +---@param port integer port to connect to +---@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient # function intended to be passed to |vim.lsp.start_client()| or |vim.lsp.start()| on the field cmd function M.connect(host, port) return function(dispatchers) dispatchers = merge_dispatchers(dispatchers) @@ -640,23 +700,82 @@ function M.connect(host, port) end end +--- Create a LSP RPC client factory that connects via named pipes (Windows) +--- or unix domain sockets (Unix) to the given pipe_path (file path on +--- Unix and name on Windows) +--- +---@param pipe_path string file path of the domain socket (Unix) or name of the named pipe (Windows) to connect to +---@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient#function intended to be passed to |vim.lsp.start_client()| or |vim.lsp.start()| on the field cmd +function M.domain_socket_connect(pipe_path) + return function(dispatchers) + dispatchers = merge_dispatchers(dispatchers) + local pipe = + assert(uv.new_pipe(false), string.format('pipe with name %s could not be opened.', pipe_path)) + local closing = false + local transport = { + write = vim.schedule_wrap(function(msg) + pipe:write(msg) + end), + is_closing = function() + return closing + end, + terminate = function() + if not closing then + closing = true + pipe:shutdown() + pipe:close() + dispatchers.on_exit(0, 0) + end + end, + } + local client = new_client(dispatchers, transport) + pipe:connect(pipe_path, function(err) + if err then + vim.schedule(function() + vim.notify( + string.format('Could not connect to :%s, reason: %s', pipe_path, vim.inspect(err)), + vim.log.levels.WARN + ) + end) + return + end + local handle_body = function(body) + client:handle_body(body) + end + pipe:read_start(M.create_read_loop(handle_body, transport.terminate, function(read_err) + client:on_error(M.client_errors.READ_ERROR, read_err) + end)) + end) + + return public_client(client) + end +end + +---@class vim.lsp.rpc.ExtraSpawnParams +---@field cwd? string Working directory for the LSP server process +---@field detached? boolean Detach the LSP server process from the current process +---@field env? table Additional environment variables for LSP server process. See |vim.system| + --- Starts an LSP server process and create an LSP RPC client object to --- interact with it. Communication with the spawned process happens via stdio. For --- communication via TCP, spawn a process manually and use |vim.lsp.rpc.connect()| --- ----@param cmd (string) Command to start the LSP server. ----@param cmd_args (table) List of additional string arguments to pass to {cmd}. ----@param dispatchers table|nil Dispatchers for LSP message types. Valid ----dispatcher names are: ---- - `"notification"` ---- - `"server_request"` ---- - `"on_error"` ---- - `"on_exit"` ----@param extra_spawn_params table|nil Additional context for the LSP +---@param cmd string Command to start the LSP server. +---@param cmd_args string[] List of additional string arguments to pass to {cmd}. +--- +---@param dispatchers? vim.lsp.rpc.Dispatchers (table|nil) Dispatchers for LSP message types. +--- Valid dispatcher names are: +--- - `"notification"` +--- - `"server_request"` +--- - `"on_error"` +--- - `"on_exit"` +--- +---@param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams (table|nil) Additional context for the LSP --- server process. May contain: --- - {cwd} (string) Working directory for the LSP server process ---- - {env} (table) Additional environment variables for LSP server process ----@return RpcClientPublic|nil Client RPC object, with these methods: +--- - {detached?} (boolean) Detach the LSP server process from the current process. Defaults to false on Windows and true otherwise. +--- - {env?} (table) Additional environment variables for LSP server process +---@return vim.lsp.rpc.PublicClient? (table|nil) client RPC object, with these methods: --- - `notify()` |vim.lsp.rpc.notify()| --- - `request()` |vim.lsp.rpc.request()| --- - `is_closing()` returns a boolean indicating if the RPC is closing. -- cgit From e0112aa1d21aa01eca867f28f77bcca28aae3b39 Mon Sep 17 00:00:00 2001 From: Mathias Fussenegger Date: Tue, 2 Jan 2024 10:19:22 +0100 Subject: refactor(lsp): fix remaining luals warnings in lsp.rpc --- runtime/lua/vim/lsp/rpc.lua | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index b0d98829a6..51d6bf4f9f 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -226,6 +226,7 @@ end ---@return vim.lsp.rpc.Error function M.rpc_response_error(code, message, data) -- TODO should this error or just pick a sane error (like InternalError)? + ---@type string local code_name = assert(protocol.ErrorCodes[code], 'Invalid RPC error code') return setmetatable({ code = code, @@ -473,6 +474,7 @@ function Client:handle_body(body) type(err) == 'table', 'err must be a table. Use rpc_response_error to help format errors.' ) + ---@type string local code_name = assert( protocol.ErrorCodes[err.code], 'Errors must use protocol.ErrorCodes. Use rpc_response_error to help format errors.' @@ -620,34 +622,24 @@ end ---@param dispatchers? vim.lsp.rpc.Dispatchers ---@return vim.lsp.rpc.Dispatchers local function merge_dispatchers(dispatchers) - if dispatchers then - local user_dispatchers = dispatchers - dispatchers = {} - for dispatch_name, default_dispatch in pairs(default_dispatchers) do - ---@cast dispatch_name string - ---@cast default_dispatch function - local user_dispatcher = user_dispatchers[dispatch_name] --- @type function - if user_dispatcher then - if type(user_dispatcher) ~= 'function' then - error(string.format('dispatcher.%s must be a function', dispatch_name)) - end - -- server_request is wrapped elsewhere. - if - not (dispatch_name == 'server_request' or dispatch_name == 'on_exit') -- TODO this blocks the loop exiting for some reason. - then - user_dispatcher = schedule_wrap(user_dispatcher) - end - --- @diagnostic disable-next-line:no-unknown - dispatchers[dispatch_name] = user_dispatcher - else - --- @diagnostic disable-next-line:no-unknown - dispatchers[dispatch_name] = default_dispatch - end + if not dispatchers then + return default_dispatchers + end + ---@diagnostic disable-next-line: no-unknown + for name, fn in pairs(dispatchers) do + if type(fn) ~= 'function' then + error(string.format('dispatcher.%s must be a function', name)) end - else - dispatchers = default_dispatchers end - return dispatchers + return { + notification = dispatchers.notification and vim.schedule_wrap(dispatchers.notification) + or default_dispatchers.notification, + on_error = dispatchers.on_error and vim.schedule_wrap(dispatchers.on_error) + or default_dispatchers.on_error, + + on_exit = dispatchers.on_exit or default_dispatchers.on_exit, + server_request = dispatchers.server_request or default_dispatchers.server_request, + } end --- Create a LSP RPC client factory that connects via TCP to the given host -- cgit From 2bf68df289de12510d472f362482e5bde253cb41 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 2 Jan 2024 19:06:43 +0800 Subject: vim-patch:10b4f75d4c03 (#26846) runtime(dist/ft): improve filetype detection for *.v (V/Verilog/Coq) Patch provided by Dan Alt closes: vim/vim#13793 https://github.com/vim/vim/commit/10b4f75d4c03c1cd4f579be5fdc812ba41b72fef Co-authored-by: Christian Brabandt --- runtime/lua/vim/filetype/detect.lua | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua index a1c5ac73b4..6a14c73c92 100644 --- a/runtime/lua/vim/filetype/detect.lua +++ b/runtime/lua/vim/filetype/detect.lua @@ -1530,12 +1530,26 @@ function M.v(_, bufnr) -- Filetype was already detected return end + if vim.g.filetype_v then + return vim.g.filetype_v + end + local in_comment = 0 for _, line in ipairs(getlines(bufnr, 1, 200)) do - if not line:find('^%s*/') then - if findany(line, { ';%s*$', ';%s*/' }) then - return 'verilog' - elseif findany(line, { '%.%s*$', '%.%s*%(%*' }) then + if line:find('^%s*/%*') then + in_comment = 1 + end + if in_comment == 1 then + if line:find('%*/') then + in_comment = 0 + end + elseif not line:find('^%s*//') then + if + line:find('%.%s*$') and not line:find('/[/*]') + or line:find('%(%*') and not line:find('/[/*].*%(%*') + then return 'coq' + elseif findany(line, { ';%s*$', ';%s*/[/*]' }) then + return 'verilog' end end end -- cgit From 5dc0bdfe98b59bb03226167ed541d17cc5af30b1 Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Tue, 2 Jan 2024 14:32:43 +0100 Subject: docs(glob): add glob module (#26853) --- runtime/lua/vim/glob.lua | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/glob.lua b/runtime/lua/vim/glob.lua index 731179d727..49d6f555da 100644 --- a/runtime/lua/vim/glob.lua +++ b/runtime/lua/vim/glob.lua @@ -2,18 +2,20 @@ local lpeg = vim.lpeg local M = {} ---- Parses a raw glob into an |lpeg| pattern. +--- Parses a raw glob into an |lua-lpeg| pattern. --- --- This uses glob semantics from LSP 3.17.0: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern +--- --- Glob patterns can have the following syntax: ---- `*` 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`) +--- - `*` 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 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`) +--- ---@param pattern string The raw glob pattern ----@return vim.lpeg.Pattern pattern An |lpeg| representation of the pattern +---@return vim.lpeg.Pattern pattern An |lua-lpeg| representation of the pattern function M.to_lpeg(pattern) local l = lpeg -- cgit From 67f53323446d45bad7a22e92493f6402316a8ba1 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Thu, 28 Dec 2023 18:00:30 -0500 Subject: fix(docs): clean up non-docstring comments for vimdoc gen These non-docstring comments can be included into doxygen's brief description and then appear in the succeeding function documentation. --- runtime/lua/vim/lsp/util.lua | 2 +- runtime/lua/vim/shared.lua | 2 +- runtime/lua/vim/text.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index ba7ce3c2b6..44465f6cff 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1069,7 +1069,7 @@ function M.show_document(location, offset_encoding, opts) -- location may be Location or LocationLink local range = location.range or location.targetSelectionRange if range then - --- Jump to new location (adjusting for encoding of characters) + -- Jump to new location (adjusting for encoding of characters) local row = range.start.line local col = get_line_byte_from_position(bufnr, range.start, offset_encoding) api.nvim_win_set_cursor(win, { row + 1, col }) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index bbbc888727..fd795aae49 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -579,7 +579,7 @@ function vim.tbl_isarray(t) local count = 0 for k, _ in pairs(t) do - --- Check if the number k is an integer + -- Check if the number k is an integer if type(k) == 'number' and k == math.floor(k) then count = count + 1 else diff --git a/runtime/lua/vim/text.lua b/runtime/lua/vim/text.lua index cfb0f9b821..576b962838 100644 --- a/runtime/lua/vim/text.lua +++ b/runtime/lua/vim/text.lua @@ -1,4 +1,4 @@ ---- Text processing functions. +-- Text processing functions. local M = {} -- cgit From 4e9298ecdf945b4d16c2c6e6e4ed82b97880917c Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Thu, 28 Dec 2023 17:50:05 -0500 Subject: refactor(gen_vimdoc): generate function doc from metadata, not from xml Problem: For function definitions to be included in the vimdoc (formatted) and to be exported as mpack data (unformatted), we had two internal representations of the same function/API metadata in duplicate; one is FunctionDoc (which was previously a dict), and the other is doxygen XML DOM from which vimdoc (functions sections) was generated. Solution: We should have a single path and unified data representation (i.e. FunctionDoc) that contains all the metadata and information about function APIs, from which both of mpack export and vimdoc are generated. I.e., vimdocs are no longer generated directly from doxygen XML nodes, but generated via: (XML DOM Nodes) ------------> FunctionDoc ------> mpack (unformatted) Recursive Internal | Formatting Metadata +---> vimdoc (formatted) This refactoring eliminates the hacky and ugly use of `fmt_vimhelp` in `fmt_node_as_vimhelp()` and all other helper functions! This way, `fmt_node_as_vimhelp()` can simplified as it no longer needs to handle generating of function docs, which needs to be done only in the topmost level of recursion. --- runtime/lua/vim/_meta/api.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index c0dfa7635b..b6ce3fce8a 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -73,6 +73,9 @@ function vim.api.nvim__id_dictionary(dct) end function vim.api.nvim__id_float(flt) end --- @private +--- NB: if your UI doesn't use hlstate, this will not return hlstate first +--- time. +--- --- @param grid integer --- @param row integer --- @param col integer -- cgit From 91d76ac941a26f8370c48e062b5e09f98c75f7bc Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Tue, 2 Jan 2024 18:52:29 +0100 Subject: docs(lsp): add supports_method to vim.lsp.client docs (#26852) --- runtime/lua/vim/lsp.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 3105413b53..27c5f7ce7b 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -425,6 +425,12 @@ end --- Runs the on_attach function from the client's config if it was defined. --- Useful for buffer-local setup. --- +--- - supports_method(method, [opts]): boolean +--- Checks if a client supports a given method. +--- Always returns true for unknown off-spec methods. +--- [opts] is a optional `{bufnr?: integer}` table. +--- Some language server capabilities can be file specific. +--- --- - Members --- - {id} (number): The id allocated to the client. --- -- cgit From 3734519e3b4ba1bf19ca772104170b0ef776be46 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 2 Jan 2024 15:47:55 +0000 Subject: feat(lua): add noref to deepcopy Problem: Currently `deepcopy` hashes every single tables it copies so it can be reused. For tables of mostly unique items that are non recursive, this hashing is unnecessarily expensive Solution: Port the `noref` argument from Vimscripts `deepcopy()`. The below benchmark demonstrates the results for two extreme cases of tables of different sizes. One table that uses the same table lots of times and one with all unique tables. | test | `noref=false` (ms) | `noref=true` (ms) | | -------------------- | ------------------ | ----------------- | | unique tables (50) | 6.59 | 2.62 | | shared tables (50) | 3.24 | 6.40 | | unique tables (2000) | 23381.48 | 2884.53 | | shared tables (2000) | 3505.54 | 14038.80 | The results are basically the inverse of each other where `noref` is much more performance on tables with unique fields, and `not noref` is more performant on tables that reuse fields. --- runtime/lua/vim/diagnostic.lua | 12 +++---- runtime/lua/vim/keymap.lua | 2 +- runtime/lua/vim/lsp.lua | 2 +- runtime/lua/vim/lsp/protocol.lua | 2 +- runtime/lua/vim/shared.lua | 70 +++++++++++++++++++++------------------- runtime/lua/vim/version.lua | 6 ++-- 6 files changed, 48 insertions(+), 46 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index a447463dff..897837a5ce 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -134,7 +134,7 @@ local function prefix_source(diagnostics) return d end - local t = vim.deepcopy(d) + local t = vim.deepcopy(d, true) t.message = string.format('%s: %s', d.source, d.message) return t end, diagnostics) @@ -146,7 +146,7 @@ local function reformat_diagnostics(format, diagnostics) diagnostics = { diagnostics, 't' }, }) - local formatted = vim.deepcopy(diagnostics) + local formatted = vim.deepcopy(diagnostics, true) for _, diagnostic in ipairs(formatted) do diagnostic.message = format(diagnostic) end @@ -373,7 +373,7 @@ local function get_diagnostics(bufnr, opts, clamp) or d.col < 0 or d.end_col < 0 then - d = vim.deepcopy(d) + d = vim.deepcopy(d, true) d.lnum = math.max(math.min(d.lnum, line_count), 0) d.end_lnum = math.max(math.min(d.end_lnum, line_count), 0) d.col = math.max(d.col, 0) @@ -636,7 +636,7 @@ function M.config(opts, namespace) if not opts then -- Return current config - return vim.deepcopy(t) + return vim.deepcopy(t, true) end for k, v in pairs(opts) do @@ -723,7 +723,7 @@ end --- ---@return table A list of active diagnostic namespaces |vim.diagnostic|. function M.get_namespaces() - return vim.deepcopy(all_namespaces) + return vim.deepcopy(all_namespaces, true) end ---@class Diagnostic @@ -756,7 +756,7 @@ function M.get(bufnr, opts) opts = { opts, 't', true }, }) - return vim.deepcopy(get_diagnostics(bufnr, opts, false)) + return vim.deepcopy(get_diagnostics(bufnr, opts, false), true) end --- Get current diagnostics count. diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua index bdea95f9ab..8e4e123fe0 100644 --- a/runtime/lua/vim/keymap.lua +++ b/runtime/lua/vim/keymap.lua @@ -44,7 +44,7 @@ function keymap.set(mode, lhs, rhs, opts) opts = { opts, 't', true }, }) - opts = vim.deepcopy(opts or {}) + opts = vim.deepcopy(opts or {}, true) ---@cast mode string[] mode = type(mode) == 'string' and { mode } or mode diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 27c5f7ce7b..b2aa943359 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1353,7 +1353,7 @@ function lsp.start_client(config) ---@param context? {bufnr: integer} ---@param handler? lsp.Handler only called if a server command function client._exec_cmd(command, context, handler) - context = vim.deepcopy(context or {}) --[[@as lsp.HandlerContext]] + context = vim.deepcopy(context or {}, true) --[[@as lsp.HandlerContext]] context.bufnr = context.bufnr or api.nvim_get_current_buf() context.client_id = client.id local cmdname = command.command diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index df12c36396..35eb0305d7 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -314,7 +314,7 @@ local constants = { } for k, v in pairs(constants) do - local tbl = vim.deepcopy(v) + local tbl = vim.deepcopy(v, true) vim.tbl_add_reverse_lookup(tbl) protocol[k] = tbl end diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index bbbc888727..87ab21a28f 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -9,43 +9,36 @@ ---@diagnostic disable-next-line: lowercase-global vim = vim or {} -local function _id(v) - return v -end +---@generic T +---@param orig T +---@param cache? table +---@return T +local function deepcopy(orig, cache) + if orig == vim.NIL then + return vim.NIL + elseif type(orig) == 'userdata' or type(orig) == 'thread' then + error('Cannot deepcopy object of type ' .. type(orig)) + elseif type(orig) ~= 'table' then + return orig + end -local deepcopy + --- @cast orig table -local deepcopy_funcs = { - table = function(orig, cache) - if cache[orig] then - return cache[orig] - end - local copy = {} + if cache and cache[orig] then + return cache[orig] + end + local copy = {} --- @type table + + if cache then cache[orig] = copy - local mt = getmetatable(orig) - for k, v in pairs(orig) do - copy[deepcopy(k, cache)] = deepcopy(v, cache) - end - return setmetatable(copy, mt) - end, - number = _id, - string = _id, - ['nil'] = _id, - boolean = _id, - ['function'] = _id, -} - -deepcopy = function(orig, _cache) - local f = deepcopy_funcs[type(orig)] - if f then - return f(orig, _cache or {}) - else - if type(orig) == 'userdata' and orig == vim.NIL then - return vim.NIL - end - error('Cannot deepcopy object of type ' .. type(orig)) end + + for k, v in pairs(orig) do + copy[deepcopy(k, cache)] = deepcopy(v, cache) + end + + return setmetatable(copy, getmetatable(orig)) end --- Returns a deep copy of the given object. Non-table objects are copied as @@ -54,11 +47,20 @@ end --- same functions as those in the input table. Userdata and threads are not --- copied and will throw an error. --- +--- Note: `noref=true` is much more performant on tables with unique table +--- fields, while `noref=false` is more performant on tables that reuse table +--- fields. +--- ---@generic T: table ---@param orig T Table to copy +---@param noref? boolean +--- When `false` (default) a contained table is only copied once and all +--- references point to this single copy. When `true` every occurrence of a +--- table results in a new copy. This also means that a cyclic reference can +--- cause `deepcopy()` to fail. ---@return T Table of copied keys and (nested) values. -function vim.deepcopy(orig) - return deepcopy(orig) +function vim.deepcopy(orig, noref) + return deepcopy(orig, not noref and {} or nil) end --- Gets an |iterator| that splits a string at each instance of a separator, in "lazy" fashion diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua index 306eef90d3..0873402e29 100644 --- a/runtime/lua/vim/version.lua +++ b/runtime/lua/vim/version.lua @@ -158,7 +158,7 @@ end function M._version(version, strict) -- Adapted from https://github.com/folke/lazy.nvim if type(version) == 'table' then if version.major then - return setmetatable(vim.deepcopy(version), Version) + return setmetatable(vim.deepcopy(version, true), Version) end return setmetatable({ major = version[1] or 0, @@ -228,7 +228,7 @@ function VersionRange:has(version) version = M.parse(version) elseif getmetatable(version) ~= Version then -- Need metatable to compare versions. - version = setmetatable(vim.deepcopy(version), Version) + version = setmetatable(vim.deepcopy(version, true), Version) end if version then if version.prerelease ~= self.from.prerelease then @@ -298,7 +298,7 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim local semver = M.parse(version) if semver then local from = semver - local to = vim.deepcopy(semver) + local to = vim.deepcopy(semver, true) if mods == '' or mods == '=' then to.patch = to.patch + 1 elseif mods == '<' then -- cgit From dc48a98f9ac614dc94739637c967aa29e064807e Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Mon, 25 Dec 2023 02:31:47 +0900 Subject: fix(decorations): validate botline for on_win Problem: Many decoration providers (treesitter injection highlighting, semantic token highlighting, inlay hint) rely on the correctness of the `botline` argument of `on_win` callback. However, `botline` can be smaller than the actual line number of the last displayed line if some lines are folded. In such cases, some decorations will be missing in the lines not covered by `botline`. Solution: Validate `botline` when invoking `on_win`. NOTE: It seems that the old code was deliberately avoiding this presumably due to performance reasons. However, I haven't experienced noticeable lag after this change, and I believe the cost of botline computation would be much smaller than the cost of decoration providers. --- runtime/lua/vim/_meta/api.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index c0dfa7635b..02128b66b9 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1761,9 +1761,7 @@ function vim.api.nvim_set_current_win(window) end --- • on_buf: called for each buffer being redrawn (before window --- callbacks) ["buf", bufnr, tick] --- • on_win: called when starting to redraw a specific window. ---- botline_guess is an approximation that does not exceed the ---- last line number. ["win", winid, bufnr, topline, ---- botline_guess] +--- ["win", winid, bufnr, topline, botline] --- • on_line: called for each buffer line being redrawn. (The --- interaction with fold lines is subject to change) ["win", --- winid, bufnr, row] -- cgit From fa61e0c047954e7eb494ee02144a4dc71a42b3b2 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Mon, 1 Jan 2024 14:24:48 +0100 Subject: refactor(column): define and use maximum 'statuscolumn' width Problem: The maximum 'statuscolumn' width and grow behavior is undocumented. Solution: Define, use and document the maximum 'statuscolumn' width and grow behavior. --- runtime/lua/vim/_meta/options.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 46497179ac..7ad720b6b2 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -6359,9 +6359,13 @@ vim.go.sol = vim.go.startofline --- %s sign column for currently drawn line --- %C fold column for currently drawn line --- ---- NOTE: To draw the sign and fold columns, their items must be included in ---- 'statuscolumn'. Even when they are not included, the status column width ---- will adapt to the 'signcolumn' and 'foldcolumn' width. +--- The 'statuscolumn' width follows that of the default columns and +--- adapts to the `'numberwidth'`, `'signcolumn'` and `'foldcolumn'` option +--- values (regardless of whether the sign and fold items are present). +--- Aditionally, the 'statuscolumn' grows with the size of the evaluated +--- format string, up to a point (following the maximum size of the default +--- fold, sign and number columns). Shrinking only happens when the number +--- of lines in a buffer changes, or the 'statuscolumn' option is set. --- --- The `v:lnum` variable holds the line number to be drawn. --- The `v:relnum` variable holds the relative line number to be drawn. -- cgit From dab584408211a39962a7313b7b8c4cb7e3717a7a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 5 Jan 2024 08:23:51 +0800 Subject: vim-patch:9.1.0010: Keymap completion is not available (#26888) Problem: Keymap completion is not available Solution: Add keymap completion (Doug Kearns) Add keymap completion to the 'keymap' option, user commands and builtin completion functions. closes: vim/vim#13692 https://github.com/vim/vim/commit/81642d9d6ff5cd6a90a012b1b98632ce51eeb1a8 Co-authored-by: Doug Kearns --- runtime/lua/vim/_meta/vimfn.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 02e794ce10..a763be93b9 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -2889,6 +2889,7 @@ function vim.fn.getcmdwintype() end --- help help subjects --- highlight highlight groups --- history |:history| suboptions +--- keymap keyboard mappings --- locale locale names (as output of locale -a) --- mapclear buffer argument --- mapping mapping name -- cgit From 8df37423781493f58de060e1c9219cd1c3768130 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Sat, 6 Jan 2024 18:08:29 -0600 Subject: fix(defaults): use augroup for default autocommands (#26933) --- runtime/lua/vim/_defaults.lua | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index af962eea5d..64eb638fd7 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -190,6 +190,8 @@ for _, ui in ipairs(vim.api.nvim_list_uis()) do end if tty then + local group = vim.api.nvim_create_augroup('nvim_tty', {}) + --- Set an option after startup (so that OptionSet is fired), but only if not --- already set by the user. --- @@ -207,6 +209,7 @@ if tty then vim.o[option] = value else vim.api.nvim_create_autocmd('VimEnter', { + group = group, once = true, nested = true, callback = function() @@ -295,6 +298,7 @@ if tty then local timer = assert(vim.uv.new_timer()) local id = vim.api.nvim_create_autocmd('TermResponse', { + group = group, nested = true, callback = function(args) local resp = args.data ---@type string @@ -370,6 +374,7 @@ if tty then local b = 3 local id = vim.api.nvim_create_autocmd('TermResponse', { + group = group, nested = true, callback = function(args) local resp = args.data ---@type string -- cgit From fbe40caa7cc1786dc58210a82901307417ba0654 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Sat, 6 Jan 2024 07:18:13 -0500 Subject: docs(treesitter): improve 'no parser' error message for InspectTree Improve error messages for `:InspectTree`, when no parsers are available for the current buffer and filetype. We can show more informative and helpful error message for users (e.g., which lang was searched for): ``` ... No parser available for the given buffer: +... no parser for 'custom_ft' language, see :help treesitter-parsers ``` Also improve the relevant docs for *treesitter-parsers*. --- runtime/lua/vim/treesitter/dev.lua | 3 ++- runtime/lua/vim/treesitter/language.lua | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 870761b7c7..399d0ef03e 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -75,7 +75,8 @@ end function TSTreeView:new(bufnr, lang) local ok, parser = pcall(vim.treesitter.get_parser, bufnr or 0, lang) if not ok then - return nil, 'No parser available for the given buffer' + local err = parser --[[ @as string ]] + return nil, 'No parser available for the given buffer:\n' .. err end -- For each child tree (injected language), find the root of the tree and locate the node within diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 2056c337c8..2105a1d992 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -119,6 +119,10 @@ local function ensure_list(x) end --- Register a parser named {lang} to be used for {filetype}(s). +--- +--- Note: this adds or overrides the mapping for {filetype}, any existing mappings from other +--- filetypes to {lang} will be preserved. +--- --- @param lang string Name of parser --- @param filetype string|string[] Filetype(s) to associate with lang function M.register(lang, filetype) -- cgit From f40df63bdca33d343cada6ceaafbc8b765ed7cc6 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Thu, 4 Jan 2024 11:09:13 -0500 Subject: fix(docs): make lines not overflow in vim docs Problem: Some lines in the generated vim doc are overflowing, not correctly wrapped at 78 characters. This happens when docs body contains several consecutive 'inline' elements generated by doxygen. Solution: Take into account the current column offset of the last line, and prepend some padding before doc_wrap(). --- runtime/lua/vim/_meta/api.lua | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index e85f81f5f9..19039eb226 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -155,7 +155,8 @@ function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start --- will be `nvim_buf_changedtick_event`. Not for Lua --- callbacks. --- @param opts vim.api.keyset.buf_attach Optional parameters. ---- • on_lines: Lua callback invoked on change. Return `true` to detach. Args: +--- • on_lines: Lua callback invoked on change. Return `true` to +--- detach. Args: --- • the string "lines" --- • buffer handle --- • b:changedtick @@ -168,7 +169,8 @@ function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start --- --- • on_bytes: Lua callback invoked on change. This --- callback receives more granular information about the ---- change compared to on_lines. Return `true` to detach. Args: +--- change compared to on_lines. Return `true` to +--- detach. Args: --- • the string "bytes" --- • buffer handle --- • b:changedtick @@ -530,7 +532,8 @@ function vim.api.nvim_buf_line_count(buffer) end --- wrapped lines. --- • hl_mode : control how highlights are combined with the --- highlights of the text. Currently only affects virt_text ---- highlights, but might affect `hl_group` in later versions. +--- highlights, but might affect `hl_group` in +--- later versions. --- • "replace": only show the virt_text color. This is the --- default. --- • "combine": combine with background text color. @@ -740,7 +743,8 @@ function vim.api.nvim_chan_send(chan, data) end --- • NOTE: Cannot be used with {pattern} --- --- • group: (string|int) The augroup name or id. ---- • NOTE: If not passed, will only delete autocmds not in any group. +--- • NOTE: If not passed, will only delete autocmds not in any +--- group. function vim.api.nvim_clear_autocmds(opts) end --- Executes an Ex command. @@ -808,7 +812,9 @@ function vim.api.nvim_complete_set(index, opts) end --- @return integer function vim.api.nvim_create_augroup(name, opts) end ---- Creates an `autocommand` event handler, defined by `callback` (Lua function or Vimscript function name string) or `command` (Ex command string). +--- Creates an `autocommand` event handler, defined by `callback` (Lua +--- function or Vimscript function name string) or `command` (Ex command +--- string). --- Example using Lua callback: --- --- ```lua @@ -1525,8 +1531,8 @@ function vim.api.nvim_open_term(buffer, opts) end --- • height: Window height (in character cells). Minimum of 1. --- • bufpos: Places float relative to buffer text (only when --- relative="win"). Takes a tuple of zero-indexed [line, ---- column]. `row` and `col` if given are applied relative to this position, else they ---- default to: +--- column]. `row` and `col` if given are +--- applied relative to this position, else they default to: --- • `row=1` and `col=0` if `anchor` is "NW" or "NE" --- • `row=0` and `col=0` if `anchor` is "SW" or "SE" (thus --- like a tooltip near the buffer text). @@ -1541,8 +1547,9 @@ function vim.api.nvim_open_term(buffer, opts) end --- • external: GUI should display the window as an external --- top-level window. Currently accepts no other positioning --- configuration together with this. ---- • zindex: Stacking order. floats with higher `zindex` go on top on floats with lower indices. Must be larger ---- than zero. The following screen elements have hard-coded +--- • zindex: Stacking order. floats with higher `zindex` go on +--- top on floats with lower indices. Must be larger than +--- zero. The following screen elements have hard-coded --- z-indices: --- • 100: insert completion popupmenu --- • 200: message scrollback @@ -1661,7 +1668,8 @@ function vim.api.nvim_parse_expression(expr, flags, highlight) end --- @param data string Multiline input. May be binary (containing NUL bytes). --- @param crlf boolean Also break lines at CR and CRLF. --- @param phase integer -1: paste in a single call (i.e. without streaming). To ---- "stream" a paste, call `nvim_paste` sequentially with these `phase` values: +--- "stream" a paste, call `nvim_paste` sequentially +--- with these `phase` values: --- • 1: starts the paste (exactly once) --- • 2: continues the paste (zero or more times) --- • 3: ends the paste (exactly once) -- cgit From beca827212b106114c371f8bb61aa1a50810062f Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Tue, 9 Jan 2024 15:27:56 +0100 Subject: feat(terminal): trigger TermRequest autocommand events (#22159) This commit implements a new TermRequest autocommand event and has Neovim emit this event when children of terminal buffers emit an OSC or DCS sequence libvterm does not handle. The TermRequest autocommand event has additional data in the v:termrequest variable. Co-authored-by: Gregory Anders --- runtime/lua/vim/_meta/vvars.lua | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vvars.lua b/runtime/lua/vim/_meta/vvars.lua index e3b89aeff7..ca87fb9d15 100644 --- a/runtime/lua/vim/_meta/vvars.lua +++ b/runtime/lua/vim/_meta/vvars.lua @@ -687,11 +687,18 @@ vim.v.t_number = ... --- @type integer vim.v.t_string = ... ---- The value of the most recent OSC or DCS escape sequence +--- The value of the most recent OSC or DCS control sequence +--- sent from a process running in the embedded `terminal`. +--- This can be read in a `TermRequest` event handler to respond +--- to queries from embedded applications. +--- @type string +vim.v.termrequest = ... + +--- The value of the most recent OSC or DCS control sequence --- received by Nvim from the terminal. This can be read in a --- `TermResponse` event handler after querying the terminal using --- another escape sequence. ---- @type any +--- @type string vim.v.termresponse = ... --- Must be set before using `test_garbagecollect_now()`. -- cgit From a767c046f4e6bff1412269d56a8edfe33857d954 Mon Sep 17 00:00:00 2001 From: JD <46619169+rudiejd@users.noreply.github.com> Date: Wed, 10 Jan 2024 21:57:51 -0500 Subject: feat(vim.iter): add Iter:flatten (#26786) Co-authored-by: Gregory Anders Co-authored-by: Jongwook Choi --- runtime/lua/vim/iter.lua | 82 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index b658dde099..c6feeea3dc 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -112,6 +112,35 @@ local function sanitize(t) return t end +--- Flattens a single list-like table. Errors if it attempts to flatten a +--- dict-like table +---@param v table table which should be flattened +---@param max_depth number depth to which the table should be flattened +---@param depth number current iteration depth +---@param result table output table that contains flattened result +---@return table|nil flattened table if it can be flattened, otherwise nil +local function flatten(v, max_depth, depth, result) + if depth < max_depth and type(v) == 'table' then + local i = 0 + for _ in pairs(v) do + i = i + 1 + + if v[i] == nil then + -- short-circuit: this is not a list like table + return nil + end + + if flatten(v[i], max_depth, depth + 1, result) == nil then + return nil + end + end + else + result[#result + 1] = v + end + + return result +end + --- Determine if the current iterator stage should continue. --- --- If any arguments are passed to this function, then return those arguments @@ -179,6 +208,54 @@ function ListIter.filter(self, f) return self end +--- Flattens a |list-iterator|, un-nesting nested values up to the given {depth}. +--- Errors if it attempts to flatten a dict-like value. +--- +--- Examples: +--- +--- ```lua +--- vim.iter({ 1, { 2 }, { { 3 } } }):flatten():totable() +--- -- { 1, 2, { 3 } } +--- +--- vim.iter({1, { { a = 2 } }, { 3 } }):flatten():totable() +--- -- { 1, { a = 2 }, 3 } +--- +--- vim.iter({ 1, { { a = 2 } }, { 3 } }):flatten(math.huge):totable() +--- -- error: attempt to flatten a dict-like table +--- ``` +--- +---@param depth? number Depth to which |list-iterator| should be flattened +--- (defaults to 1) +---@return Iter +function Iter.flatten(self, depth) -- luacheck: no unused args + error('flatten() requires a list-like table') +end + +---@private +function ListIter.flatten(self, depth) + depth = depth or 1 + local inc = self._head < self._tail and 1 or -1 + local target = {} + + for i = self._head, self._tail - inc, inc do + local flattened = flatten(self._table[i], depth, 0, {}) + + -- exit early if we try to flatten a dict-like table + if flattened == nil then + error('flatten() requires a list-like table') + end + + for _, v in pairs(flattened) do + target[#target + 1] = v + end + end + + self._head = 1 + self._tail = #target + 1 + self._table = target + return self +end + --- Maps the items of an iterator pipeline to the values returned by `f`. --- --- If the map function returns nil, the value is filtered from the iterator. @@ -461,9 +538,8 @@ end --- ``` --- ---@return Iter -function Iter.rev(self) +function Iter.rev(self) -- luacheck: no unused args error('rev() requires a list-like table') - return self end ---@private @@ -733,7 +809,6 @@ end ---@diagnostic disable-next-line: unused-local function Iter.skipback(self, n) -- luacheck: no unused args error('skipback() requires a list-like table') - return self end ---@private @@ -800,7 +875,6 @@ end ---@diagnostic disable-next-line: unused-local function Iter.slice(self, first, last) -- luacheck: no unused args error('slice() requires a list-like table') - return self end ---@private -- cgit From 2f9ee9b6cfc61a0504fc0bc22bdf481828e2ea91 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 9 Jan 2024 17:36:46 +0000 Subject: fix(doc): improve doc generation of types using lpeg Added a lpeg grammar for LuaCATS and use it in lua2dox.lua --- runtime/lua/vim/_editor.lua | 7 +++--- runtime/lua/vim/_meta/api.lua | 5 ++-- runtime/lua/vim/_system.lua | 4 +-- runtime/lua/vim/filetype.lua | 4 +-- runtime/lua/vim/health.lua | 2 +- runtime/lua/vim/iter.lua | 48 ++++++++++++++++++------------------ runtime/lua/vim/lsp/handlers.lua | 2 +- runtime/lua/vim/lsp/util.lua | 6 ++--- runtime/lua/vim/shared.lua | 2 +- runtime/lua/vim/treesitter/query.lua | 2 +- 10 files changed, 40 insertions(+), 42 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index cde61697b6..4fe601dfd5 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -95,7 +95,7 @@ vim.log = { --- throws an error if {cmd} cannot be run. --- --- @param cmd (string[]) Command to execute ---- @param opts (SystemOpts|nil) Options: +--- @param opts vim.SystemOpts? Options: --- - cwd: (string) Set the current working directory for the sub-process. --- - env: table Set environment variables for the new process. Inherits the --- current environment with `NVIM` set to |v:servername|. @@ -118,7 +118,7 @@ vim.log = { --- parent exits. Note that the child process will still keep the parent's event loop alive --- unless the parent process calls |uv.unref()| on the child's process handle. --- ---- @param on_exit (function|nil) Called when subprocess exits. When provided, the command runs +--- @param on_exit? fun(out: vim.SystemCompleted) Called when subprocess exits. When provided, the command runs --- asynchronously. Receives SystemCompleted object, see return of SystemObj:wait(). --- --- @return vim.SystemObj Object with the fields: @@ -219,10 +219,9 @@ do --- ``` --- ---@see |paste| - ---@alias paste_phase -1 | 1 | 2 | 3 --- ---@param lines string[] # |readfile()|-style list of lines to paste. |channel-lines| - ---@param phase paste_phase -1: "non-streaming" paste: the call contains all lines. + ---@param phase (-1|1|2|3) -1: "non-streaming" paste: the call contains all lines. --- If paste is "streamed", `phase` indicates the stream state: --- - 1: starts the paste (exactly once) --- - 2: continues the paste (zero or more times) diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 19039eb226..3f06d4fd43 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -812,9 +812,8 @@ function vim.api.nvim_complete_set(index, opts) end --- @return integer function vim.api.nvim_create_augroup(name, opts) end ---- Creates an `autocommand` event handler, defined by `callback` (Lua ---- function or Vimscript function name string) or `command` (Ex command ---- string). +--- Creates an `autocommand` event handler, defined by `callback` (Lua function +--- or Vimscript function name string) or `command` (Ex command string). --- Example using Lua callback: --- --- ```lua diff --git a/runtime/lua/vim/_system.lua b/runtime/lua/vim/_system.lua index 9279febddf..9e935b7e95 100644 --- a/runtime/lua/vim/_system.lua +++ b/runtime/lua/vim/_system.lua @@ -1,6 +1,6 @@ local uv = vim.uv ---- @class SystemOpts +--- @class vim.SystemOpts --- @field stdin? string|string[]|true --- @field stdout? fun(err:string?, data: string?)|false --- @field stderr? fun(err:string?, data: string?)|false @@ -302,7 +302,7 @@ end --- Run a system command --- --- @param cmd string[] ---- @param opts? SystemOpts +--- @param opts? vim.SystemOpts --- @param on_exit? fun(out: vim.SystemCompleted) --- @return vim.SystemObj function M.run(cmd, opts, on_exit) diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 9141b1e4c6..8cd5f19569 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -2165,7 +2165,7 @@ end --- } --- ``` --- ----@param filetypes vim.filetype.add.filetypes A table containing new filetype maps (see example). +---@param filetypes vim.filetype.add.filetypes (table) A table containing new filetype maps (see example). function M.add(filetypes) for k, v in pairs(filetypes.extension or {}) do extension[k] = v @@ -2300,7 +2300,7 @@ end --- vim.filetype.match({ contents = {'#!/usr/bin/env bash'} }) --- ``` --- ----@param args vim.filetype.match.args Table specifying which matching strategy to use. +---@param args vim.filetype.match.args (table) Table specifying which matching strategy to use. --- Accepted keys are: --- * buf (number): Buffer number to use for matching. Mutually exclusive with --- {contents} diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua index d9265f6bd6..f6f7abef8f 100644 --- a/runtime/lua/vim/health.lua +++ b/runtime/lua/vim/health.lua @@ -315,7 +315,7 @@ end --- Run a system command and timeout after 30 seconds. --- --- @param cmd table List of command arguments to execute ---- @param args ?table Optional arguments: +--- @param args? table Optional arguments: --- - stdin (string): Data to write to the job's stdin --- - stderr (boolean): Append stderr to stdout --- - ignore_error (boolean): If true, ignore error output diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index c6feeea3dc..a63d5ba565 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -181,9 +181,9 @@ end --- local bufs = vim.iter(vim.api.nvim_list_bufs()):filter(vim.api.nvim_buf_is_loaded) --- ``` --- ----@param f function(...):bool Takes all values returned from the previous stage ---- in the pipeline and returns false or nil if the ---- current iterator element should be removed. +---@param f fun(...):bool Takes all values returned from the previous stage +--- in the pipeline and returns false or nil if the +--- current iterator element should be removed. ---@return Iter function Iter.filter(self, f) return self:map(function(...) @@ -272,11 +272,11 @@ end --- -- { 6, 12 } --- ``` --- ----@param f function(...):any Mapping function. Takes all values returned from ---- the previous stage in the pipeline as arguments ---- and returns one or more new values, which are used ---- in the next pipeline stage. Nil return values ---- are filtered from the output. +---@param f fun(...):any Mapping function. Takes all values returned from +--- the previous stage in the pipeline as arguments +--- and returns one or more new values, which are used +--- in the next pipeline stage. Nil return values +--- are filtered from the output. ---@return Iter function Iter.map(self, f) -- Implementation note: the reader may be forgiven for observing that this @@ -340,9 +340,9 @@ end --- --- For functions with side effects. To modify the values in the iterator, use |Iter:map()|. --- ----@param f function(...) Function to execute for each item in the pipeline. ---- Takes all of the values returned by the previous stage ---- in the pipeline as arguments. +---@param f fun(...) Function to execute for each item in the pipeline. +--- Takes all of the values returned by the previous stage +--- in the pipeline as arguments. function Iter.each(self, f) local function fn(...) if select(1, ...) ~= nil then @@ -464,7 +464,7 @@ end ---@generic A --- ---@param init A Initial value of the accumulator. ----@param f function(acc:A, ...):A Accumulation function. +---@param f fun(acc:A, ...):A Accumulation function. ---@return A function Iter.fold(self, init, f) local acc = init @@ -884,9 +884,9 @@ end --- Returns true if any of the items in the iterator match the given predicate. --- ----@param pred function(...):bool Predicate function. Takes all values returned from the previous ---- stage in the pipeline as arguments and returns true if the ---- predicate matches. +---@param pred fun(...):bool Predicate function. Takes all values returned from the previous +--- stage in the pipeline as arguments and returns true if the +--- predicate matches. function Iter.any(self, pred) local any = false @@ -908,9 +908,9 @@ end --- Returns true if all items in the iterator match the given predicate. --- ----@param pred function(...):bool Predicate function. Takes all values returned from the previous ---- stage in the pipeline as arguments and returns true if the ---- predicate matches. +---@param pred fun(...):bool Predicate function. Takes all values returned from the previous +--- stage in the pipeline as arguments and returns true if the +--- predicate matches. function Iter.all(self, pred) local all = true @@ -1106,9 +1106,9 @@ end --- ---@see |Iter:filter()| --- ----@param f function(...):bool Filter function. Accepts the current iterator or table values as ---- arguments and returns true if those values should be kept in the ---- final table +---@param f fun(...):bool Filter function. Accepts the current iterator or table values as +--- arguments and returns true if those values should be kept in the +--- final table ---@param src table|function Table or iterator function to filter ---@return table function M.filter(f, src, ...) @@ -1124,9 +1124,9 @@ end --- ---@see |Iter:map()| --- ----@param f function(...):?any Map function. Accepts the current iterator or table values as ---- arguments and returns one or more new values. Nil values are removed ---- from the final table. +---@param f fun(...): any? Map function. Accepts the current iterator or table values as +--- arguments and returns one or more new values. Nil values are removed +--- from the final table. ---@param src table|function Table or iterator function to filter ---@return table function M.map(f, src, ...) diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index c03a17fa59..daf09b6430 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -516,7 +516,7 @@ end --- --- Displays call hierarchy in the quickfix window. --- ----@param direction `"from"` for incoming calls and `"to"` for outgoing calls +---@param direction 'from'|'to' `"from"` for incoming calls and `"to"` for outgoing calls ---@return function --- `CallHierarchyIncomingCall[]` if {direction} is `"from"`, --- `CallHierarchyOutgoingCall[]` if {direction} is `"to"`, diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 44465f6cff..a2cc81781a 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -790,7 +790,7 @@ end --- Note that if the input is of type `MarkupContent` and its kind is `plaintext`, --- then the corresponding value is returned without further modifications. --- ----@param input (`MarkedString` | `MarkedString[]` | `MarkupContent`) +---@param input (lsp.MarkedString | lsp.MarkedString[] | lsp.MarkupContent) ---@param contents (table|nil) List of strings to extend with converted lines. Defaults to {}. ---@return string[] extended with lines of converted markdown. ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover @@ -2115,8 +2115,8 @@ end --- Returns the UTF-32 and UTF-16 offsets for a position in a certain buffer. --- ---@param buf integer buffer number (0 for current) ----@param row 0-indexed line ----@param col 0-indexed byte offset in line +---@param row integer 0-indexed line +---@param col integer 0-indexed byte offset in line ---@param offset_encoding string utf-8|utf-16|utf-32 defaults to `offset_encoding` of first client of `buf` ---@return integer `offset_encoding` index of the character in line {row} column {col} in buffer {buf} function M.character_offset(buf, row, col, offset_encoding) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 24bc97bf8e..e76d148b1b 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -875,7 +875,7 @@ end --- a.b.c = 1 --- ``` --- ----@param createfn function?(key:any):any Provides the value for a missing `key`. +---@param createfn? fun(key:any):any Provides the value for a missing `key`. ---@return table # Empty table with `__index` metamethod. function vim.defaulttable(createfn) createfn = createfn or function(_) diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 8cbbffcd60..cc8fe319e8 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -793,7 +793,7 @@ end --- of the query file, e.g., if the path ends in `/lua/highlights.scm`, the parser for the --- `lua` language will be used. ---@param buf (integer) Buffer handle ----@param opts (QueryLinterOpts|nil) Optional keyword arguments: +---@param opts? QueryLinterOpts (table) Optional keyword arguments: --- - langs (string|string[]|nil) Language(s) to use for checking the query. --- If multiple languages are specified, queries are validated for all of them --- - clear (boolean) if `true`, just clear current lint errors -- cgit From 2bdd8fad4cf4008125ce540453434888c07044a6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 14 Jan 2024 08:44:16 +0800 Subject: docs(builtin): fix mapset() signature (#27008) --- runtime/lua/vim/_meta/vimfn.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index a763be93b9..f044871601 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -5152,6 +5152,12 @@ function vim.fn.maplist() end --- @return any function vim.fn.mapnew(expr1, expr2) end +--- @param mode string +--- @param abbr? any +--- @param dict? any +--- @return any +function vim.fn.mapset(mode, abbr, dict) end + --- Restore a mapping from a dictionary, possibly returned by --- |maparg()| or |maplist()|. A buffer mapping, when dict.buffer --- is true, is set on the current buffer; it is up to the caller @@ -5187,11 +5193,9 @@ function vim.fn.mapnew(expr1, expr2) end --- call mapset(d) --- endfor --- ---- @param mode string ---- @param abbr? any ---- @param dict? any +--- @param dict any --- @return any -function vim.fn.mapset(mode, abbr, dict) end +function vim.fn.mapset(dict) end --- When {expr} is a |List| then this returns the index of the --- first item where {pat} matches. Each item is used as a -- cgit From ce4ea638c703275aedadb3794efc56dcb782c908 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Tue, 9 Jan 2024 18:04:27 -0500 Subject: fix(lsp): fix incorrect typing and doc for `vim.lsp.rpc` Typings introduced in #26032 and #26552 have a few conflicts, so we merge and clean them up. We also fix some incorrect type annotation in the `vim.lsp.rpc` package. See the associated PR for more details. Summary: - vim.rpc.Dispatchers -> vim.lsp.rpc.Dispatchers - vim.lsp.rpc.Error -> lsp.ResponseError - Revise docs --- runtime/lua/vim/_system.lua | 4 +- runtime/lua/vim/lsp.lua | 8 ++- runtime/lua/vim/lsp/rpc.lua | 172 ++++++++++++++++++++++---------------------- 3 files changed, 93 insertions(+), 91 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_system.lua b/runtime/lua/vim/_system.lua index 9e935b7e95..efad3f88cf 100644 --- a/runtime/lua/vim/_system.lua +++ b/runtime/lua/vim/_system.lua @@ -61,7 +61,7 @@ end --- @field wait fun(self: vim.SystemObj, timeout?: integer): vim.SystemCompleted --- @field kill fun(self: vim.SystemObj, signal: integer|string) --- @field write fun(self: vim.SystemObj, data?: string|string[]) ---- @field is_closing fun(self: vim.SystemObj): boolean? +--- @field is_closing fun(self: vim.SystemObj): boolean local SystemObj = {} --- @param state vim.SystemState @@ -140,7 +140,7 @@ end --- @return boolean function SystemObj:is_closing() local handle = self._state.handle - return handle == nil or handle:is_closing() + return handle == nil or handle:is_closing() or false end ---@param output fun(err:string?, data: string?)|false diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index b2aa943359..a02a93d559 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -258,7 +258,7 @@ end --- Validates a client configuration as given to |vim.lsp.start_client()|. --- ---@param config (lsp.ClientConfig) ----@return (string|fun(dispatchers:vim.rpc.Dispatchers):RpcClientPublic?) Command +---@return (string|fun(dispatchers:vim.rpc.Dispatchers):vim.lsp.rpc.PublicClient?) Command ---@return string[] Arguments ---@return string Encoding. local function validate_client_config(config) @@ -291,7 +291,7 @@ local function validate_client_config(config) 'flags.debounce_text_changes must be a number with the debounce time in milliseconds' ) - local cmd, cmd_args --- @type (string|fun(dispatchers:vim.rpc.Dispatchers):RpcClientPublic), string[] + local cmd, cmd_args --- @type (string|fun(dispatchers:vim.rpc.Dispatchers):vim.lsp.rpc.PublicClient), string[] local config_cmd = config.cmd if type(config_cmd) == 'function' then cmd = config_cmd @@ -826,6 +826,8 @@ function lsp.start_client(config) --- ---@param method (string) LSP method name ---@param params (table) The parameters for that method + ---@return any result + ---@return lsp.ResponseError error code and message set in case an exception happens during the request. function dispatch.server_request(method, params) if log.trace() then log.trace('server_request', method, params) @@ -953,7 +955,7 @@ function lsp.start_client(config) end -- Start the RPC client. - local rpc --- @type RpcClientPublic? + local rpc --- @type vim.lsp.rpc.PublicClient? if type(cmd) == 'function' then rpc = cmd(dispatch) else diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 51d6bf4f9f..660b126ce4 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -5,29 +5,6 @@ local validate, schedule, schedule_wrap = vim.validate, vim.schedule, vim.schedu local is_win = uv.os_uname().version:find('Windows') ----@alias vim.lsp.rpc.Dispatcher fun(method: string, params: table):nil, vim.lsp.rpc.Error? ----@alias vim.lsp.rpc.on_error fun(code: integer, ...: any) ----@alias vim.lsp.rpc.on_exit fun(code: integer, signal: integer) - ----@class vim.lsp.rpc.Dispatchers ----@field notification vim.lsp.rpc.Dispatcher ----@field server_request vim.lsp.rpc.Dispatcher ----@field on_exit vim.lsp.rpc.on_error ----@field on_error vim.lsp.rpc.on_exit - ----@class vim.lsp.rpc.PublicClient ----@field request fun(method: string, params?: table, callback: fun(err: lsp.ResponseError | nil, result: any), notify_reply_callback:function?) ----@field notify fun(method: string, params: any) ----@field is_closing fun(): boolean ----@field terminate fun(): nil - ----@class vim.lsp.rpc.Client ----@field message_index integer ----@field message_callbacks table dict of message_id to callback ----@field notify_reply_callbacks table dict of message_id to callback ----@field transport vim.lsp.rpc.Transport ----@field dispatchers vim.lsp.rpc.Dispatchers - --- Checks whether a given path exists and is a directory. ---@param filename string path to check ---@return boolean @@ -186,7 +163,7 @@ M.client_errors = vim.tbl_add_reverse_lookup(M.client_errors) --- Constructs an error message from an LSP error object. --- ---@param err table The error object ----@return string#The formatted error message +---@return string error_message The formatted error message function M.format_rpc_error(err) validate({ err = { err, 't' }, @@ -213,17 +190,14 @@ function M.format_rpc_error(err) return table.concat(message_parts, ' ') end ----@class vim.lsp.rpc.Error ----@field code integer RPC error code defined by JSON RPC, see `vim.lsp.protocol.ErrorCodes` ----@field message? string arbitrary message to send to server ----@field data? any arbitrary data to send to server - ---- Creates an RPC response object/table. +--- Creates an RPC response table `error` to be sent to the LSP response. --- ----@param code integer RPC error code defined by JSON RPC +---@param code integer RPC error code defined, see `vim.lsp.protocol.ErrorCodes` ---@param message? string arbitrary message to send to server ---@param data? any arbitrary data to send to server ----@return vim.lsp.rpc.Error +--- +---@see lsp.ErrorCodes See `vim.lsp.protocol.ErrorCodes` +---@return lsp.ResponseError function M.rpc_response_error(code, message, data) -- TODO should this error or just pick a sane error (like InternalError)? ---@type string @@ -237,28 +211,28 @@ function M.rpc_response_error(code, message, data) }) end ---- @class vim.rpc.Dispatchers +--- @class vim.lsp.rpc.Dispatchers --- @field notification fun(method: string, params: table) ---- @field server_request fun(method: string, params: table): any?, string? +--- @field server_request fun(method: string, params: table): any?, lsp.ResponseError? --- @field on_exit fun(code: integer, signal: integer) --- @field on_error fun(code: integer, err: any) ---- @type vim.rpc.Dispatchers +--- @type vim.lsp.rpc.Dispatchers local default_dispatchers = { --- Default dispatcher for notifications sent to an LSP server. --- - ---@param method (string) The invoked LSP method - ---@param params (table) Parameters for the invoked LSP method + ---@param method string The invoked LSP method + ---@param params table Parameters for the invoked LSP method notification = function(method, params) log_debug('notification', method, params) end, --- Default dispatcher for requests sent to an LSP server. --- - ---@param method (string) The invoked LSP method - ---@param params (table) Parameters for the invoked LSP method - ---@return nil - ---@return vim.lsp.rpc.Error#`vim.lsp.protocol.ErrorCodes.MethodNotFound` + ---@param method string The invoked LSP method + ---@param params table Parameters for the invoked LSP method + ---@return any result (always nil for the default dispatchers) + ---@return lsp.ResponseError error `vim.lsp.protocol.ErrorCodes.MethodNotFound` server_request = function(method, params) log_debug('server_request', method, params) return nil, M.rpc_response_error(protocol.ErrorCodes.MethodNotFound) @@ -266,25 +240,21 @@ local default_dispatchers = { --- Default dispatcher for when a client exits. --- - ---@param code (integer) Exit code - ---@param signal (integer) Number describing the signal used to terminate (if - ---any) + ---@param code integer Exit code + ---@param signal integer Number describing the signal used to terminate (if any) on_exit = function(code, signal) log_info('client_exit', { code = code, signal = signal }) end, --- Default dispatcher for client errors. --- - ---@param code (integer) Error code - ---@param err (any) Details about the error - ---any) + ---@param code integer Error code + ---@param err any Details about the error on_error = function(code, err) log_error('client_error:', M.client_errors[code], err) end, } ----@cast default_dispatchers vim.lsp.rpc.Dispatchers - ---@private function M.create_read_loop(handle_body, on_no_chunk, on_error) local parse_chunk = coroutine.wrap(request_parser_loop) --[[@as fun(chunk: string?): vim.lsp.rpc.Headers?, string?]] @@ -314,6 +284,14 @@ function M.create_read_loop(handle_body, on_no_chunk, on_error) end end +---@private +---@class vim.lsp.rpc.Client +---@field message_index integer +---@field message_callbacks table dict of message_id to callback +---@field notify_reply_callbacks table dict of message_id to callback +---@field transport vim.lsp.rpc.Transport +---@field dispatchers vim.lsp.rpc.Dispatchers + ---@class vim.lsp.rpc.Client local Client = {} @@ -356,13 +334,14 @@ function Client:send_response(request_id, err, result) end ---@package ---- Sends a request to the LSP server and runs {callback} upon response. +--- Sends a request to the LSP server and runs {callback} upon response. |vim.lsp.rpc.request()| --- ---@param method string The invoked LSP method ----@param params? table Parameters for the invoked LSP method +---@param params table? Parameters for the invoked LSP method ---@param callback fun(err?: lsp.ResponseError, result: any) Callback to invoke ----@param notify_reply_callback? function Callback to invoke as soon as a request is no longer pending ----@return boolean success, integer|nil request_id true, request_id if request could be sent, `false` if not +---@param notify_reply_callback fun(message_id: integer)|nil Callback to invoke as soon as a request is no longer pending +---@return boolean success `true` if request could be sent, `false` if not +---@return integer? message_id if request could be sent, `nil` if not function Client:request(method, params, callback, notify_reply_callback) validate({ callback = { callback, 'f' }, @@ -382,14 +361,14 @@ function Client:request(method, params, callback, notify_reply_callback) if message_callbacks then message_callbacks[message_id] = schedule_wrap(callback) else - return false + return false, nil end if notify_reply_callback and notify_reply_callbacks then notify_reply_callbacks[message_id] = schedule_wrap(notify_reply_callback) end return result, message_id else - return false + return false, nil end end @@ -443,7 +422,7 @@ function Client:handle_body(body) log_debug('rpc.receive', decoded) if type(decoded.method) == 'string' and decoded.id then - local err --- @type vim.lsp.rpc.Error? + local err --- @type lsp.ResponseError|nil -- Schedule here so that the users functions don't trigger an error and -- we can still use the result. schedule(function() @@ -469,7 +448,7 @@ function Client:handle_body(body) ) end if err then - ---@cast err vim.lsp.rpc.Error + ---@cast err lsp.ResponseError assert( type(err) == 'table', 'err must be a table. Use rpc_response_error to help format errors.' @@ -564,9 +543,9 @@ function Client:handle_body(body) end ---@class vim.lsp.rpc.Transport ----@field write fun(msg: string): nil ----@field is_closing fun(): boolean|nil ----@field terminate fun(): nil +---@field write fun(msg: string) +---@field is_closing fun(): boolean +---@field terminate fun() ---@param dispatchers vim.lsp.rpc.Dispatchers ---@param transport vim.lsp.rpc.Transport @@ -582,9 +561,17 @@ local function new_client(dispatchers, transport) return setmetatable(state, { __index = Client }) end +---@class vim.lsp.rpc.PublicClient +---@field request fun(method: string, params: table?, callback: fun(err: lsp.ResponseError|nil, result: any), notify_reply_callback: fun(integer)|nil):boolean,integer? see |vim.lsp.rpc.request()| +---@field notify fun(method: string, params: any):boolean see |vim.lsp.rpc.notify()| +---@field is_closing fun(): boolean +---@field terminate fun() + ---@param client vim.lsp.rpc.Client ---@return vim.lsp.rpc.PublicClient local function public_client(client) + ---@type vim.lsp.rpc.PublicClient + ---@diagnostic disable-next-line: missing-fields local result = {} ---@private @@ -601,9 +588,10 @@ local function public_client(client) --- ---@param method (string) The invoked LSP method ---@param params (table?) Parameters for the invoked LSP method - ---@param callback fun(err: lsp.ResponseError | nil, result: any) Callback to invoke - ---@param notify_reply_callback (function?) Callback to invoke as soon as a request is no longer pending - ---@return boolean success, integer|nil request_id true, message_id if request could be sent, `false` if not + ---@param callback fun(err: lsp.ResponseError|nil, result: any) Callback to invoke + ---@param notify_reply_callback fun(message_id: integer)|nil Callback to invoke as soon as a request is no longer pending + ---@return boolean success `true` if request could be sent, `false` if not + ---@return integer? message_id if request could be sent, `nil` if not function result.request(method, params, callback, notify_reply_callback) return client:request(method, params, callback, notify_reply_callback) end @@ -619,7 +607,7 @@ local function public_client(client) return result end ----@param dispatchers? vim.lsp.rpc.Dispatchers +---@param dispatchers vim.lsp.rpc.Dispatchers? ---@return vim.lsp.rpc.Dispatchers local function merge_dispatchers(dispatchers) if not dispatchers then @@ -631,23 +619,30 @@ local function merge_dispatchers(dispatchers) error(string.format('dispatcher.%s must be a function', name)) end end - return { - notification = dispatchers.notification and vim.schedule_wrap(dispatchers.notification) - or default_dispatchers.notification, - on_error = dispatchers.on_error and vim.schedule_wrap(dispatchers.on_error) - or default_dispatchers.on_error, - + ---@type vim.lsp.rpc.Dispatchers + local merged = { + notification = ( + dispatchers.notification and vim.schedule_wrap(dispatchers.notification) + or default_dispatchers.notification + ), + on_error = ( + dispatchers.on_error and vim.schedule_wrap(dispatchers.on_error) + or default_dispatchers.on_error + ), on_exit = dispatchers.on_exit or default_dispatchers.on_exit, server_request = dispatchers.server_request or default_dispatchers.server_request, } + return merged end ---- Create a LSP RPC client factory that connects via TCP to the given host ---- and port +--- Create a LSP RPC client factory that connects via TCP to the given host and port. +--- +--- Return a function that can be passed to the `cmd` field for +--- |vim.lsp.start_client()| or |vim.lsp.start()|. --- ---@param host string host to connect to ---@param port integer port to connect to ----@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient # function intended to be passed to |vim.lsp.start_client()| or |vim.lsp.start()| on the field cmd +---@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient function M.connect(host, port) return function(dispatchers) dispatchers = merge_dispatchers(dispatchers) @@ -694,10 +689,13 @@ end --- Create a LSP RPC client factory that connects via named pipes (Windows) --- or unix domain sockets (Unix) to the given pipe_path (file path on ---- Unix and name on Windows) +--- Unix and name on Windows). +--- +--- Return a function that can be passed to the `cmd` field for +--- |vim.lsp.start_client()| or |vim.lsp.start()|. --- ---@param pipe_path string file path of the domain socket (Unix) or name of the named pipe (Windows) to connect to ----@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient#function intended to be passed to |vim.lsp.start_client()| or |vim.lsp.start()| on the field cmd +---@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient function M.domain_socket_connect(pipe_path) return function(dispatchers) dispatchers = merge_dispatchers(dispatchers) @@ -755,23 +753,25 @@ end ---@param cmd string Command to start the LSP server. ---@param cmd_args string[] List of additional string arguments to pass to {cmd}. --- ----@param dispatchers? vim.lsp.rpc.Dispatchers (table|nil) Dispatchers for LSP message types. +---@param dispatchers? vim.lsp.rpc.Dispatchers Dispatchers for LSP message types. --- Valid dispatcher names are: --- - `"notification"` --- - `"server_request"` --- - `"on_error"` --- - `"on_exit"` --- ----@param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams (table|nil) Additional context for the LSP +---@param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams Additional context for the LSP --- server process. May contain: ---- - {cwd} (string) Working directory for the LSP server process ---- - {detached?} (boolean) Detach the LSP server process from the current process. Defaults to false on Windows and true otherwise. ---- - {env?} (table) Additional environment variables for LSP server process ----@return vim.lsp.rpc.PublicClient? (table|nil) client RPC object, with these methods: ---- - `notify()` |vim.lsp.rpc.notify()| ---- - `request()` |vim.lsp.rpc.request()| ---- - `is_closing()` returns a boolean indicating if the RPC is closing. ---- - `terminate()` terminates the RPC client. +--- - {cwd} (string) Working directory for the LSP server process +--- - {detached?} (boolean) Detach the LSP server process from the current process. +--- Defaults to false on Windows and true otherwise. +--- - {env?} (table) Additional environment variables for LSP server process +--- +---@return vim.lsp.rpc.PublicClient? Client RPC object, with these methods: +--- - `notify()` |vim.lsp.rpc.notify()| +--- - `request()` |vim.lsp.rpc.request()| +--- - `is_closing()` returns a boolean indicating if the RPC is closing. +--- - `terminate()` terminates the RPC client. function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) log_info('Starting RPC client', { cmd = cmd, args = cmd_args, extra = extra_spawn_params }) @@ -846,7 +846,7 @@ function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) end local msg = string.format('Spawning language server with cmd: `%s` failed%s', cmd, sfx) vim.notify(msg, vim.log.levels.WARN) - return + return nil end sysobj = sysobj_or_err --[[@as vim.SystemObj]] -- cgit From 2cdea852e8934beb89012f2127f333e4dd8aada8 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Thu, 11 Jan 2024 12:24:44 -0500 Subject: docs: auto-generate docs for `vim.lpeg` and `vim.re` - Add section `VIM.LPEG` and `VIM.RE` to docs/lua.txt. - Add `_meta/re.lua` which adds luadoc and type annotations, for the vendored `vim.re` package. - Fix minor style issues on `_meta/lpeg.lua` luadoc for better vimdocs generation. - Fix a bug on `gen_vimdoc` where non-helptags in verbatim code blocks were parsed as helptags, affecting code examples on `vim.lpeg.Cf`, etc. - Also move the `vim.regex` section below so that it can be located closer to `vim.lpeg` and `vim.re`. --- runtime/lua/vim/_meta/lpeg.lua | 32 +++++++++++++++++++++--- runtime/lua/vim/_meta/re.lua | 57 ++++++++++++++++++++++++++++++++++++++++++ runtime/lua/vim/re.lua | 1 + 3 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 runtime/lua/vim/_meta/re.lua (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/lpeg.lua b/runtime/lua/vim/_meta/lpeg.lua index 42c9a6449e..5bd502a7c8 100644 --- a/runtime/lua/vim/_meta/lpeg.lua +++ b/runtime/lua/vim/_meta/lpeg.lua @@ -1,7 +1,24 @@ --- @meta +error('Cannot require a meta file') --- These types were taken from https://github.com/LuaCATS/lpeg, with types being renamed to include --- the vim namespace and with some descriptions made less verbose. +-- These types were taken from https://github.com/LuaCATS/lpeg +-- (based on revision 4aded588f9531d89555566bb1de27490354b91c7) +-- with types being renamed to include the vim namespace and with some descriptions made less verbose. + +---@defgroup vim.lpeg +---
help
+---LPeg is a pattern-matching library for Lua, based on
+---Parsing Expression Grammars (https://bford.info/packrat/) (PEGs).
+---
+---                                                                    *lua-lpeg*
+---                                                            *vim.lpeg.Pattern*
+---The LPeg library for parsing expression grammars is included as `vim.lpeg`
+---(https://www.inf.puc-rio.br/~roberto/lpeg/).
+---
+---In addition, its regex-like interface is available as |vim.re|
+---(https://www.inf.puc-rio.br/~roberto/lpeg/re.html).
+---
+---
--- *LPeg* is a new pattern-matching library for Lua, based on [Parsing Expression Grammars](https://bford.info/packrat/) (PEGs). vim.lpeg = {} @@ -32,6 +49,7 @@ local Pattern = {} --- matches anywhere. --- --- Example: +--- --- ```lua --- local pattern = lpeg.R("az") ^ 1 * -1 --- assert(pattern:match("hello") == 6) @@ -55,6 +73,7 @@ function vim.lpeg.match(pattern, subject, init) end --- we must either write a loop in Lua or write a pattern that matches anywhere. --- --- Example: +--- --- ```lua --- local pattern = lpeg.R("az") ^ 1 * -1 --- assert(pattern:match("hello") == 6) @@ -69,7 +88,7 @@ function Pattern:match(subject, init) end --- Returns the string `"pattern"` if the given value is a pattern, otherwise `nil`. --- ---- @return 'pattern'|nil +--- @return "pattern"|nil function vim.lpeg.type(value) end --- Returns a string with the running version of LPeg. @@ -115,6 +134,7 @@ function vim.lpeg.B(pattern) end --- `lpeg.R("az", "AZ")` matches any ASCII letter. --- --- Example: +--- --- ```lua --- local pattern = lpeg.R("az") ^ 1 * -1 --- assert(pattern:match("hello") == 6) @@ -137,6 +157,7 @@ function vim.lpeg.S(string) end --- for a grammar. The created non-terminal refers to the rule indexed by `v` in the enclosing grammar. --- --- Example: +--- --- ```lua --- local b = lpeg.P({"(" * ((1 - lpeg.S "()") + lpeg.V(1)) ^ 0 * ")"}) --- assert(b:match('((string))') == 11) @@ -168,6 +189,7 @@ function vim.lpeg.V(v) end --- that table. --- --- Example: +--- --- ```lua --- lpeg.locale(lpeg) --- local space = lpeg.space^0 @@ -191,6 +213,7 @@ function vim.lpeg.locale(tab) end --- The captured value is a string. If `patt` has other captures, their values are returned after this one. --- --- Example: +--- --- ```lua --- local function split (s, sep) --- sep = lpeg.P(sep) @@ -241,6 +264,7 @@ function vim.lpeg.Cc(...) end --- becomes the captured value. --- --- Example: +--- --- ```lua --- local number = lpeg.R("09") ^ 1 / tonumber --- local list = number * ("," * number) ^ 0 @@ -267,6 +291,7 @@ function vim.lpeg.Cg(patt, name) end --- subject where the match occurs. The captured value is a number. --- --- Example: +--- --- ```lua --- local I = lpeg.Cp() --- local function anywhere(p) return lpeg.P({I * p * I + 1 * lpeg.V(1)}) end @@ -285,6 +310,7 @@ function vim.lpeg.Cp() end --- value is the string resulting from all replacements. --- --- Example: +--- --- ```lua --- local function gsub (s, patt, repl) --- patt = lpeg.P(patt) diff --git a/runtime/lua/vim/_meta/re.lua b/runtime/lua/vim/_meta/re.lua new file mode 100644 index 0000000000..4f254b19a0 --- /dev/null +++ b/runtime/lua/vim/_meta/re.lua @@ -0,0 +1,57 @@ +--- @meta +error('Cannot require a meta file') + +-- Documentations and Lua types for vim.re (vendored re.lua, lpeg-1.1.0) +-- https://www.inf.puc-rio.br/~roberto/lpeg/re.html +-- +-- Copyright © 2007-2023 Lua.org, PUC-Rio. +-- See 'lpeg.html' for license + +--- @defgroup vim.re +---
help
+---The `vim.re` module provides a conventional regex-like syntax for pattern usage
+---within LPeg |vim.lpeg|.
+---
+---See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original
+---documentation including regex syntax and more concrete examples.
+---
+---
+ +--- Compiles the given {string} and returns an equivalent LPeg pattern. The given string may define +--- either an expression or a grammar. The optional {defs} table provides extra Lua values to be used +--- by the pattern. +--- @param string string +--- @param defs? table +--- @return vim.lpeg.Pattern +function vim.re.compile(string, defs) end + +--- Searches the given {pattern} in the given {subject}. If it finds a match, returns the index +--- where this occurrence starts and the index where it ends. Otherwise, returns nil. +--- +--- An optional numeric argument {init} makes the search starts at that position in the subject +--- string. As usual in Lua libraries, a negative value counts from the end. +--- @param subject string +--- @param pattern vim.lpeg.Pattern|string +--- @param init? integer +--- @return integer|nil the index where the occurrence starts, nil if no match +--- @return integer|nil the index where the occurrence ends, nil if no match +function vim.re.find(subject, pattern, init) end + +--- Does a global substitution, replacing all occurrences of {pattern} in the given {subject} by +--- {replacement}. +--- @param subject string +--- @param pattern vim.lpeg.Pattern|string +--- @param replacement string +--- @return string +function vim.re.gsub(subject, pattern, replacement) end + +--- Matches the given {pattern} against the given {subject}, returning all captures. +--- @param subject string +--- @param pattern vim.lpeg.Pattern|string +--- @param init? integer +--- @return integer|vim.lpeg.Capture|nil +--- @see vim.lpeg.match() +function vim.re.match(subject, pattern, init) end + +--- Updates the pre-defined character classes to the current locale. +function vim.re.updatelocale() end diff --git a/runtime/lua/vim/re.lua b/runtime/lua/vim/re.lua index 007eb27ed8..114f74eb80 100644 --- a/runtime/lua/vim/re.lua +++ b/runtime/lua/vim/re.lua @@ -3,6 +3,7 @@ -- written by Roberto Ierusalimschy -- --- vendored from lpeg-1.1.0 +--- documentation available at runtime/lua/vim/_meta/re.lua -- imported functions and modules local tonumber, type, print, error = tonumber, type, print, error -- cgit From e5ff71fbbfea0431826a82a6de24656d93651ec3 Mon Sep 17 00:00:00 2001 From: altermo Date: Sun, 14 Jan 2024 12:10:31 +0100 Subject: docs(builtin): overload functions with union return types --- runtime/lua/vim/_meta/vimfn.lua | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index f044871601..fd9b68a6f3 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -1843,7 +1843,13 @@ function vim.fn.exp(expr) end --- --- @param string string --- @param nosuf? boolean ---- @param list? any +--- @param list? nil|false +--- @return string +function vim.fn.expand(string, nosuf, list) end + +--- @param string string +--- @param nosuf boolean +--- @param list true|number|string|table --- @return string|string[] function vim.fn.expand(string, nosuf, list) end @@ -3138,7 +3144,12 @@ function vim.fn.getjumplist(winnr, tabnr) end --- |getbufoneline()| --- --- @param lnum integer ---- @param end_? any +--- @param end_? nil|false +--- @return string +function vim.fn.getline(lnum, end_) end + +--- @param lnum integer +--- @param end_ true|number|string|table --- @return string|string[] function vim.fn.getline(lnum, end_) end @@ -3436,7 +3447,12 @@ function vim.fn.getqflist(what) end --- If {regname} is not specified, |v:register| is used. --- --- @param regname? string ---- @param list? any +--- @param list? nil|false +--- @return string +function vim.fn.getreg(regname, list) end + +--- @param regname string +--- @param list true|number|string|table --- @return string|string[] function vim.fn.getreg(regname, list) end @@ -5067,7 +5083,14 @@ function vim.fn.map(expr1, expr2) end --- @param name string --- @param mode? string --- @param abbr? boolean ---- @param dict? boolean +--- @param dict? false +--- @return string +function vim.fn.maparg(name, mode, abbr, dict) end + +--- @param name string +--- @param mode string +--- @param abbr boolean +--- @param dict true --- @return string|table function vim.fn.maparg(name, mode, abbr, dict) end @@ -9317,7 +9340,12 @@ function vim.fn.strwidth(string) end --- A line break is included as a newline character. --- --- @param nr integer ---- @param list? integer +--- @param list? nil +--- @return string +function vim.fn.submatch(nr, list) end + +--- @param nr integer +--- @param list integer --- @return string|string[] function vim.fn.submatch(nr, list) end -- cgit From 4d91604c8868b7afaf429cc16b72192ce89ea698 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Sun, 14 Jan 2024 22:37:07 -0500 Subject: docs: add lua typing for `vim.NIL` --- runtime/lua/vim/_meta/builtin.lua | 9 ++++++++- runtime/lua/vim/_meta/vvars.lua | 2 +- runtime/lua/vim/lsp/util.lua | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua index eeba356672..dd849e5247 100644 --- a/runtime/lua/vim/_meta/builtin.lua +++ b/runtime/lua/vim/_meta/builtin.lua @@ -1,7 +1,8 @@ ---@meta - -- luacheck: no unused args +error('Cannot require a meta file') + ---@defgroup vim.builtin --- ---@brief
help
@@ -62,6 +63,12 @@
 ---
 ---
+---@class vim.NIL + +---@type vim.NIL +---@nodoc +vim.NIL = ... + --- Returns true if the code is executing as part of a "fast" event handler, --- where most of the API is disabled. These are low-level events (e.g. --- |lua-loop-callbacks|) which can be invoked whenever Nvim polls for input. diff --git a/runtime/lua/vim/_meta/vvars.lua b/runtime/lua/vim/_meta/vvars.lua index ca87fb9d15..958b4a7ccd 100644 --- a/runtime/lua/vim/_meta/vvars.lua +++ b/runtime/lua/vim/_meta/vvars.lua @@ -427,7 +427,7 @@ vim.v.msgpack_types = ... --- In some places `v:null` can be used for a List, Dict, etc. --- that is not set. That is slightly different than an empty --- List, Dict, etc. ---- @type any +--- @type vim.NIL vim.v.null = ... --- Maximum value of a number. diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index a2cc81781a..50890e37ce 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -2139,7 +2139,7 @@ end --- ---@param settings table language server settings ---@param section string indicating the field of the settings table ----@return table|string The value of settings accessed via section +---@return table|string|vim.NIL The value of settings accessed via section. `vim.NIL` if not found. function M.lookup_section(settings, section) for part in vim.gsplit(section, '.', { plain = true }) do settings = settings[part] -- cgit From fa836cb98b54dd170db485529cbeddb43c307ee1 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Sat, 6 Jan 2024 08:59:50 -0500 Subject: docs(vvars): fix wrong lua types in vim.v variables - cmdarg: string[] -> string - shell_error: string -> int - stderr: string -> int - Add types for: cmdbang, errors, exception, false, true --- runtime/lua/vim/_meta/vvars.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vvars.lua b/runtime/lua/vim/_meta/vvars.lua index 958b4a7ccd..ee6d8ddf35 100644 --- a/runtime/lua/vim/_meta/vvars.lua +++ b/runtime/lua/vim/_meta/vvars.lua @@ -34,14 +34,14 @@ vim.v.charconvert_to = ... --- leading space to make it possible to append this variable --- directly after the read/write command. Note: "+cmd" isn't --- included here, because it will be executed anyway. ---- @type string[] +--- @type string vim.v.cmdarg = ... --- Set like v:cmdarg for a file read/write command. When a "!" --- was used the value is 1, otherwise it is 0. Note that this --- can only be used in autocommands. For user commands `` --- can be used. ---- @type any +--- @type integer vim.v.cmdbang = ... --- The current locale setting for collation order of the runtime @@ -141,7 +141,7 @@ vim.v.errmsg = ... --- --- If v:errors is set to anything but a list it is made an empty --- list by the assert function. ---- @type any +--- @type string[] vim.v.errors = ... --- Dictionary of event data for the current `autocommand`. Valid @@ -210,7 +210,7 @@ vim.v.event = ... --- ``` --- --- Output: "caught oops". ---- @type any +--- @type string vim.v.exception = ... --- Exit code, or `v:null` before invoking the `VimLeavePre` @@ -228,7 +228,7 @@ vim.v.exiting = ... --- as a String (e.g. in `expr5` with string concatenation --- operator) and to zero when used as a Number (e.g. in `expr5` --- or `expr7` when used with numeric operators). Read-only. ---- @type any +--- @type boolean vim.v['false'] = ... --- What should happen after a `FileChangedShell` event was @@ -608,7 +608,7 @@ vim.v.servername = ... --- echo 'could not rename "foo" to "bar"!' --- endif --- ``` ---- @type string +--- @type integer vim.v.shell_error = ... --- Last given status message. @@ -624,7 +624,7 @@ vim.v.statusmsg = ... --- ```vim --- :call chansend(v:stderr, "error: toaster empty\n") --- ``` ---- @type string +--- @type integer vim.v.stderr = ... --- `SwapExists` autocommands can set this to the selected choice @@ -733,7 +733,7 @@ vim.v.throwpoint = ... --- as a String (e.g. in `expr5` with string concatenation --- operator) and to one when used as a Number (e.g. in `expr5` or --- `expr7` when used with numeric operators). Read-only. ---- @type any +--- @type boolean vim.v['true'] = ... --- Value of the current item of a `List` or `Dictionary`. Only -- cgit From 7589336120a258cf75134a5243b2f6b1926ac85b Mon Sep 17 00:00:00 2001 From: Daniel Steinberg Date: Mon, 15 Jan 2024 11:12:07 -0500 Subject: feat(terminal): respond to OSC background and foreground request (#17197) The motivation for this update is Issue #15365, where background=light is not properly set for Nvim running from an Nvim :terminal. This can be encountered when e.g., opening a terminal to make git commits, which opens EDITOR=nvim in the nested terminal. Under the implementation of this commit, the OSC response always indicates a black or white foreground/background. While this may not reflect the actual foreground/background color, it permits 'background' to be retained for a nested Nvim instance running in the terminal emulator. The behaviour matches Vim. --- runtime/lua/vim/_defaults.lua | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 64eb638fd7..07850a5a47 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -155,6 +155,30 @@ do end, }) + vim.api.nvim_create_autocmd('TermRequest', { + group = nvim_terminal_augroup, + desc = 'Respond to OSC foreground/background color requests', + callback = function(args) + local fg_request = args.data == '\027]10;?' + local bg_request = args.data == '\027]11;?' + if fg_request or bg_request then + -- WARN: This does not return the actual foreground/background color, + -- but rather returns: + -- - fg=white/bg=black when Nvim option 'background' is 'dark' + -- - fg=black/bg=white when Nvim option 'background' is 'light' + local red, green, blue = 0, 0, 0 + local bg_option_dark = vim.o.background == 'dark' + if (fg_request and bg_option_dark) or (bg_request and not bg_option_dark) then + red, green, blue = 65535, 65535, 65535 + end + local command = fg_request and 10 or 11 + local data = string.format('\027]%d;rgb:%04x/%04x/%04x\007', command, red, green, blue) + local channel = vim.bo[args.buf].channel + vim.api.nvim_chan_send(channel, data) + end + end, + }) + vim.api.nvim_create_autocmd('CmdwinEnter', { pattern = '[:>]', desc = 'Limit syntax sync to maxlines=1 in the command window', -- cgit From 73e1942abe7a96d63ce3749af4187f2cdff87e69 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 16 Jan 2024 08:00:08 +0800 Subject: vim-patch:9.1.0009: Cannot easily get the list of matches (#27028) Problem: Cannot easily get the list of matches Solution: Add the matchstrlist() and matchbufline() Vim script functions (Yegappan Lakshmanan) closes: vim/vim#13766 Omit CHECK_LIST_MATERIALIZE(): it populates a List with numbers only, and there is a check for strings below. https://github.com/vim/vim/commit/f93b1c881a99fa847a1bafa71877d7e16f18e6ef vim-patch:eb3475df0d92 runtime(doc): Replace non-breaking space with normal space (vim/vim#13868) https://github.com/vim/vim/commit/eb3475df0d927a178789cf8e7fc4983932e1cdbe Co-authored-by: Yegappan Lakshmanan <4298407+yegappan@users.noreply.github.com> --- runtime/lua/vim/_meta/vimfn.lua | 85 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index fd9b68a6f3..01b4ef920b 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -5412,6 +5412,54 @@ function vim.fn.matchaddpos(group, pos, priority, id, dict) end --- @return any function vim.fn.matcharg(nr) end +--- Returns the |List| of matches in lines from {lnum} to {end} in +--- buffer {buf} where {pat} matches. +--- +--- {lnum} and {end} can either be a line number or the string "$" +--- to refer to the last line in {buf}. +--- +--- The {dict} argument supports following items: +--- submatches include submatch information (|/\(|) +--- +--- For each match, a |Dict| with the following items is returned: +--- byteidx starting byte index of the match +--- lnum line number where there is a match +--- text matched string +--- Note that there can be multiple matches in a single line. +--- +--- This function works only for loaded buffers. First call +--- |bufload()| if needed. +--- +--- When {buf} is not a valid buffer, the buffer is not loaded or +--- {lnum} or {end} is not valid then an error is given and an +--- empty |List| is returned. +--- +--- Examples: >vim +--- " Assuming line 3 in buffer 5 contains "a" +--- :echo matchbufline(5, '\<\k\+\>', 3, 3) +--- [{'lnum': 3, 'byteidx': 0, 'text': 'a'}] +--- " Assuming line 4 in buffer 10 contains "tik tok" +--- :echo matchbufline(10, '\<\k\+\>', 1, 4) +--- [{'lnum': 4, 'byteidx': 0, 'text': 'tik'}, {'lnum': 4, 'byteidx': 4, 'text': 'tok'}] +--- < +--- If {submatch} is present and is v:true, then submatches like +--- "\1", "\2", etc. are also returned. Example: >vim +--- " Assuming line 2 in buffer 2 contains "acd" +--- :echo matchbufline(2, '\(a\)\?\(b\)\?\(c\)\?\(.*\)', 2, 2 +--- \ {'submatches': v:true}) +--- [{'lnum': 2, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}] +--- vim +--- :echo matchstrlist(['tik tok'], '\<\k\+\>') +--- [{'idx': 0, 'byteidx': 0, 'text': 'tik'}, {'idx': 0, 'byteidx': 4, 'text': 'tok'}] +--- :echo matchstrlist(['a', 'b'], '\<\k\+\>') +--- [{'idx': 0, 'byteidx': 0, 'text': 'a'}, {'idx': 1, 'byteidx': 0, 'text': 'b'}] +--- < +--- If "submatches" is present and is v:true, then submatches like +--- "\1", "\2", etc. are also returned. Example: >vim +--- :echo matchstrlist(['acd'], '\(a\)\?\(b\)\?\(c\)\?\(.*\)', +--- \ #{submatches: v:true}) +--- [{'idx': 0, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}] +--- vim --- echo matchstrpos("testing", "ing") @@ -5612,7 +5695,7 @@ function vim.fn.matchstrpos(expr, pat, start, count) end --- it returns the maximum of all values in the Dictionary. --- If {expr} is neither a List nor a Dictionary, or one of the --- items in {expr} cannot be used as a Number this results in ---- an error. An empty |List| or |Dictionary| results in zero. +--- an error. An empty |List| or |Dictionary| results in zero. --- --- @param expr any --- @return any -- cgit From 46a7c1b3193d1f4ba09cd66ce03a1e2340d324a7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 16 Jan 2024 11:30:35 +0800 Subject: vim-patch:partial:9.1.0027: Vim is missing a foreach() func (#27037) Problem: Vim is missing a foreach() func Solution: Implement foreach({expr1}, {expr2}) function, which applies {expr2} for each item in {expr1} without changing it (Ernie Rael) closes: vim/vim#12166 https://github.com/vim/vim/commit/e79e2077607e8f829ba823308c91104a795736ba Partial port as this doesn't handle non-materialized range() lists. vim-patch:c92b8bed1fa6 runtime(help): delete duplicate help tag E741 (vim/vim#13861) https://github.com/vim/vim/commit/c92b8bed1fa632569c8358feb3b72dd6a0844ef7 Co-authored-by: Ernie Rael --- runtime/lua/vim/_meta/vimfn.lua | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 01b4ef920b..59497f96e9 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -2308,6 +2308,45 @@ function vim.fn.foldtext() end --- @return string function vim.fn.foldtextresult(lnum) end +--- {expr1} must be a |List|, |String|, |Blob| or |Dictionary|. +--- For each item in {expr1} execute {expr2}. {expr1} is not +--- modified; its values may be, as with |:lockvar| 1. |E741| +--- See |map()| and |filter()| to modify {expr1}. +--- +--- {expr2} must be a |string| or |Funcref|. +--- +--- If {expr2} is a |string|, inside {expr2} |v:val| has the value +--- of the current item. For a |Dictionary| |v:key| has the key +--- of the current item and for a |List| |v:key| has the index of +--- the current item. For a |Blob| |v:key| has the index of the +--- current byte. For a |String| |v:key| has the index of the +--- current character. +--- Examples: > +--- call foreach(mylist, 'let used[v:val] = v:true') +--- Date: Tue, 16 Jan 2024 12:07:35 +0800 Subject: docs(builtin): remove signatures of undocumented functions (#27039) Having an empty signature causes an empty line in generated docs, so remove it. Also change ">" to ">vim" in foreach() docs. --- runtime/lua/vim/_meta/vimfn.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 59497f96e9..50f6e4da52 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -2321,7 +2321,7 @@ function vim.fn.foldtextresult(lnum) end --- the current item. For a |Blob| |v:key| has the index of the --- current byte. For a |String| |v:key| has the index of the --- current character. ---- Examples: > +--- Examples: >vim --- call foreach(mylist, 'let used[v:val] = v:true') --- Date: Tue, 9 Jan 2024 12:47:57 +0000 Subject: fix(diagnostic): typing --- runtime/lua/vim/F.lua | 5 +- runtime/lua/vim/diagnostic.lua | 521 +++++++++++++++++++++++++++++------------ 2 files changed, 368 insertions(+), 158 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/F.lua b/runtime/lua/vim/F.lua index 5ed60ca8ab..8eb17a4c95 100644 --- a/runtime/lua/vim/F.lua +++ b/runtime/lua/vim/F.lua @@ -14,8 +14,9 @@ local F = {} --- assert(vim.F.if_nil(a, b, c, d) == 42) --- ``` --- ----@param ... any ----@return any +---@generic T +---@param ... T +---@return T function F.if_nil(...) local nargs = select('#', ...) for i = 1, nargs do diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 897837a5ce..c7a1e8ebd3 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -2,15 +2,87 @@ local api, if_nil = vim.api, vim.F.if_nil local M = {} ----@enum DiagnosticSeverity +--- @class vim.Diagnostic +--- @field bufnr? integer +--- @field lnum integer 0-indexed +--- @field end_lnum? integer 0-indexed +--- @field col integer 0-indexed +--- @field end_col? integer 0-indexed +--- @field severity? vim.diagnostic.Severity +--- @field message string +--- @field source? string +--- @field code? string +--- @field _tags? { deprecated: boolean, unnecessary: boolean} +--- @field user_data? any arbitrary data plugins can add +--- @field namespace? integer + +--- @class vim.diagnostic.Opts +--- @field float? boolean|vim.diagnostic.Opts.Float +--- @field update_in_insert? boolean +--- @field underline? boolean|vim.diagnostic.Opts.Underline +--- @field virtual_text? boolean|vim.diagnostic.Opts.VirtualText +--- @field signs? boolean|vim.diagnostic.Opts.Signs +--- @field severity_sort? boolean|{reverse?:boolean} + +--- @class vim.diagnostic.OptsResolved +--- @field float vim.diagnostic.Opts.Float +--- @field update_in_insert boolean +--- @field underline vim.diagnostic.Opts.Underline +--- @field virtual_text vim.diagnostic.Opts.VirtualText +--- @field signs vim.diagnostic.Opts.Signs +--- @field severity_sort {reverse?:boolean} + +--- @class vim.diagnostic.Opts.Float +--- @field bufnr? integer +--- @field namespace? integer +--- @field scope? 'line'|'buffer'|'cursor'|'c'|'l'|'b' +--- @field pos? integer|{[1]:integer,[2]:integer} +--- @field severity_sort? boolean|{reverse?:boolean} +--- @field severity? vim.diagnostic.Severity +--- @field header? string|{[1]:string,[2]:any} +--- @field source? boolean|string +--- @field format? fun(diagnostic:vim.Diagnostic): string +--- @field prefix? string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string) +--- @field suffix? string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string) +--- @field focus_id? string + +--- @class vim.diagnostic.Opts.Underline +--- @field severity? vim.diagnostic.Severity + +--- @class vim.diagnostic.Opts.VirtualText +--- @field severity? vim.diagnostic.Severity +--- @field source? boolean|string +--- @field prefix? string|function +--- @field suffix? string|function +--- @field spacing? integer +--- @field format? function +--- @field hl_mode? 'replace'|'combine'|'blend' +--- @field virt_text? {[1]:string,[2]:any}[] +--- @field virt_text_pos? 'eol'|'overlay'|'right_align'|'inline' +--- @field virt_text_win_col? integer +--- @field virt_text_hide? boolean + +--- @class vim.diagnostic.Opts.Signs +--- @field severity? vim.diagnostic.Severity +--- @field priority? integer +--- @field text? table +--- @field numhl? table +--- @field linehl? table +--- @field texthl? table + +--- @enum vim.diagnostic.Severity M.severity = { ERROR = 1, WARN = 2, INFO = 3, HINT = 4, + [1] = 'ERROR', + [2] = 'WARN', + [3] = 'INFO', + [4] = 'HINT', } -vim.tbl_add_reverse_lookup(M.severity) +--- @alias vim.diagnostic.SeverityInt 1|2|3|4 -- Mappings from qflist/loclist error types to severities M.severity.E = M.severity.ERROR @@ -18,6 +90,7 @@ M.severity.W = M.severity.WARN M.severity.I = M.severity.INFO M.severity.N = M.severity.HINT +--- @type vim.diagnostic.Opts local global_diagnostic_options = { signs = true, underline = true, @@ -27,6 +100,11 @@ local global_diagnostic_options = { severity_sort = false, } +--- @class vim.diagnostic.Handler +--- @field show? fun(namespace: integer, bufnr: integer, diagnostics: vim.Diagnostic[], opts?: vim.diagnostic.OptsResolved) +--- @field hide? fun(namespace:integer, bufnr:integer) + +--- @type table M.handlers = setmetatable({}, { __newindex = function(t, name, handler) vim.validate({ handler = { handler, 't' } }) @@ -39,6 +117,9 @@ M.handlers = setmetatable({}, { -- Metatable that automatically creates an empty table when assigning to a missing key local bufnr_and_namespace_cacher_mt = { + --- @param t table + --- @param bufnr integer + --- @return table __index = function(t, bufnr) assert(bufnr > 0, 'Invalid buffer number') t[bufnr] = {} @@ -46,10 +127,13 @@ local bufnr_and_namespace_cacher_mt = { end, } -local diagnostic_cache +-- bufnr -> ns -> Diagnostic[] +local diagnostic_cache = {} --- @type table> do local group = api.nvim_create_augroup('DiagnosticBufWipeout', {}) - diagnostic_cache = setmetatable({}, { + setmetatable(diagnostic_cache, { + --- @param t table + --- @param bufnr integer __index = function(t, bufnr) assert(bufnr > 0, 'Invalid buffer number') api.nvim_create_autocmd('BufWipeout', { @@ -65,13 +149,35 @@ do }) end +--- @class vim.diagnostic._extmark +--- @field [1] integer id +--- @field [2] integer start +--- @field [3] integer end +--- @field [4] table details + +--- @type table> local diagnostic_cache_extmarks = setmetatable({}, bufnr_and_namespace_cacher_mt) + +--- @type table local diagnostic_attached_buffers = {} + +--- @type table> local diagnostic_disabled = {} + +--- @type table> local bufs_waiting_to_update = setmetatable({}, bufnr_and_namespace_cacher_mt) +--- @class vim.diagnostic.NS +--- @field name string +--- @field opts vim.diagnostic.Opts +--- @field user_data table +--- @field disabled? boolean + +--- @type table local all_namespaces = {} +---@param severity string|vim.diagnostic.Severity +---@return vim.diagnostic.Severity? local function to_severity(severity) if type(severity) == 'string' then return assert( @@ -82,45 +188,56 @@ local function to_severity(severity) return severity end +--- @param severity vim.diagnostic.Severity|vim.diagnostic.Severity[]|{min:vim.diagnostic.Severity,max:vim.diagnostic.Severity} +--- @param diagnostics vim.Diagnostic[] +--- @return vim.Diagnostic[] local function filter_by_severity(severity, diagnostics) if not severity then return diagnostics end if type(severity) ~= 'table' then - severity = to_severity(severity) + severity = assert(to_severity(severity)) + --- @param t vim.Diagnostic return vim.tbl_filter(function(t) return t.severity == severity end, diagnostics) end if severity.min or severity.max then + --- @cast severity {min:vim.diagnostic.Severity,max:vim.diagnostic.Severity} local min_severity = to_severity(severity.min) or M.severity.HINT local max_severity = to_severity(severity.max) or M.severity.ERROR + --- @param t vim.Diagnostic return vim.tbl_filter(function(t) return t.severity <= min_severity and t.severity >= max_severity end, diagnostics) end - local severities = {} + --- @cast severity vim.diagnostic.Severity[] + + local severities = {} --- @type table for _, s in ipairs(severity) do - severities[to_severity(s)] = true + severities[assert(to_severity(s))] = true end - --- @param t table + --- @param t vim.Diagnostic return vim.tbl_filter(function(t) return severities[t.severity] end, diagnostics) end +--- @param bufnr integer +--- @return integer local function count_sources(bufnr) - local seen = {} + local seen = {} --- @type table local count = 0 for _, namespace_diagnostics in pairs(diagnostic_cache[bufnr]) do for _, diagnostic in ipairs(namespace_diagnostics) do - if diagnostic.source and not seen[diagnostic.source] then - seen[diagnostic.source] = true + local source = diagnostic.source + if source and not seen[source] then + seen[source] = true count = count + 1 end end @@ -128,7 +245,10 @@ local function count_sources(bufnr) return count end +--- @param diagnostics vim.Diagnostic[] +--- @return vim.Diagnostic[] local function prefix_source(diagnostics) + --- @param d vim.Diagnostic return vim.tbl_map(function(d) if not d.source then return d @@ -140,6 +260,8 @@ local function prefix_source(diagnostics) end, diagnostics) end +--- @param diagnostics vim.Diagnostic[] +--- @return vim.Diagnostic[] local function reformat_diagnostics(format, diagnostics) vim.validate({ format = { format, 'f' }, @@ -153,26 +275,35 @@ local function reformat_diagnostics(format, diagnostics) return formatted end +--- @param option string +--- @param namespace integer? +--- @return table local function enabled_value(option, namespace) local ns = namespace and M.get_namespace(namespace) or {} if ns.opts and type(ns.opts[option]) == 'table' then return ns.opts[option] end - if type(global_diagnostic_options[option]) == 'table' then - return global_diagnostic_options[option] + local global_opt = global_diagnostic_options[option] + if type(global_opt) == 'table' then + return global_opt end return {} end +--- @param option string +--- @param value any? +--- @param namespace integer? +--- @param bufnr integer +--- @return any local function resolve_optional_value(option, value, namespace, bufnr) if not value then return false elseif value == true then return enabled_value(option, namespace) elseif type(value) == 'function' then - local val = value(namespace, bufnr) + local val = value(namespace, bufnr) --- @type any if val == true then return enabled_value(option, namespace) else @@ -180,15 +311,18 @@ local function resolve_optional_value(option, value, namespace, bufnr) end elseif type(value) == 'table' then return value - else - error('Unexpected option type: ' .. vim.inspect(value)) end + error('Unexpected option type: ' .. vim.inspect(value)) end +--- @param opts vim.diagnostic.Opts? +--- @param namespace integer? +--- @param bufnr integer +--- @return vim.diagnostic.OptsResolved local function get_resolved_options(opts, namespace, bufnr) local ns = namespace and M.get_namespace(namespace) or {} -- Do not use tbl_deep_extend so that an empty table can be used to reset to default values - local resolved = vim.tbl_extend('keep', opts or {}, ns.opts or {}, global_diagnostic_options) + local resolved = vim.tbl_extend('keep', opts or {}, ns.opts or {}, global_diagnostic_options) --- @type table for k in pairs(global_diagnostic_options) do if resolved[k] ~= nil then resolved[k] = resolve_optional_value(k, resolved[k], namespace, bufnr) @@ -205,9 +339,11 @@ local diagnostic_severities = { [M.severity.HINT] = { ctermfg = 7, guifg = 'LightGrey' }, } --- Make a map from DiagnosticSeverity -> Highlight Name +--- Make a map from vim.diagnostic.Severity -> Highlight Name +--- @param base_name string +--- @return table local function make_highlight_map(base_name) - local result = {} + local result = {} --- @type table for k in pairs(diagnostic_severities) do local name = M.severity[k] name = name:sub(1, 1) .. name:sub(2):lower() @@ -217,6 +353,8 @@ local function make_highlight_map(base_name) return result end +-- TODO(lewis6991): these highlight maps can only be indexed with an integer, however there usage +-- implies they can be indexed with any vim.diagnostic.Severity local virtual_text_highlight_map = make_highlight_map('VirtualText') local underline_highlight_map = make_highlight_map('Underline') local floating_highlight_map = make_highlight_map('Floating') @@ -229,12 +367,14 @@ local function get_bufnr(bufnr) return bufnr end +--- @param diagnostics vim.Diagnostic[] +--- @return table local function diagnostic_lines(diagnostics) if not diagnostics then return {} end - local diagnostics_by_line = {} + local diagnostics_by_line = {} --- @type table for _, diagnostic in ipairs(diagnostics) do local line_diagnostics = diagnostics_by_line[diagnostic.lnum] if not line_diagnostics then @@ -246,6 +386,9 @@ local function diagnostic_lines(diagnostics) return diagnostics_by_line end +--- @param namespace integer +--- @param bufnr integer +--- @param diagnostics vim.Diagnostic[] local function set_diagnostic_cache(namespace, bufnr, diagnostics) for _, diagnostic in ipairs(diagnostics) do assert(diagnostic.lnum, 'Diagnostic line number is required') @@ -260,10 +403,12 @@ local function set_diagnostic_cache(namespace, bufnr, diagnostics) diagnostic_cache[bufnr][namespace] = diagnostics end +--- @param bufnr integer +--- @param last integer local function restore_extmarks(bufnr, last) for ns, extmarks in pairs(diagnostic_cache_extmarks[bufnr]) do local extmarks_current = api.nvim_buf_get_extmarks(bufnr, ns, 0, -1, { details = true }) - local found = {} + local found = {} --- @type table for _, extmark in ipairs(extmarks_current) do -- nvim_buf_set_lines will move any extmark to the line after the last -- nvim_buf_set_text will move any extmark to the last line @@ -281,6 +426,8 @@ local function restore_extmarks(bufnr, last) end end +--- @param namespace integer +--- @param bufnr? integer local function save_extmarks(namespace, bufnr) bufnr = get_bufnr(bufnr) if not diagnostic_attached_buffers[bufnr] then @@ -298,6 +445,7 @@ local function save_extmarks(namespace, bufnr) api.nvim_buf_get_extmarks(bufnr, namespace, 0, -1, { details = true }) end +--- @type table local registered_autocmds = {} local function make_augroup_key(namespace, bufnr) @@ -305,6 +453,8 @@ local function make_augroup_key(namespace, bufnr) return string.format('DiagnosticInsertLeave:%s:%s', bufnr, ns.name) end +--- @param namespace integer +--- @param bufnr integer local function execute_scheduled_display(namespace, bufnr) local args = bufs_waiting_to_update[bufnr][namespace] if not args then @@ -320,6 +470,9 @@ end --- Table of autocmd events to fire the update for displaying new diagnostic information local insert_leave_auto_cmds = { 'InsertLeave', 'CursorHoldI' } +--- @param namespace integer +--- @param bufnr integer +--- @param args any[] local function schedule_display(namespace, bufnr, args) bufs_waiting_to_update[bufnr][namespace] = args @@ -338,6 +491,8 @@ local function schedule_display(namespace, bufnr, args) end end +--- @param namespace integer +--- @param bufnr integer local function clear_scheduled_display(namespace, bufnr) local key = make_augroup_key(namespace, bufnr) @@ -347,6 +502,10 @@ local function clear_scheduled_display(namespace, bufnr) end end +--- @param bufnr integer? +--- @param opts vim.diagnostic.GetOpts? +--- @param clamp boolean +--- @return vim.Diagnostic[] local function get_diagnostics(bufnr, opts, clamp) opts = opts or {} @@ -354,13 +513,19 @@ local function get_diagnostics(bufnr, opts, clamp) local diagnostics = {} -- Memoized results of buf_line_count per bufnr + --- @type table local buf_line_count = setmetatable({}, { + --- @param t table + --- @param k integer + --- @return integer __index = function(t, k) t[k] = api.nvim_buf_line_count(k) return rawget(t, k) end, }) + ---@param b integer + ---@param d vim.Diagnostic local function add(b, d) if not opts.lnum or d.lnum == opts.lnum then if clamp and api.nvim_buf_is_loaded(b) then @@ -375,7 +540,7 @@ local function get_diagnostics(bufnr, opts, clamp) then d = vim.deepcopy(d, true) d.lnum = math.max(math.min(d.lnum, line_count), 0) - d.end_lnum = math.max(math.min(d.end_lnum, line_count), 0) + d.end_lnum = math.max(math.min(assert(d.end_lnum), line_count), 0) d.col = math.max(d.col, 0) d.end_col = math.max(d.end_col, 0) end @@ -384,6 +549,8 @@ local function get_diagnostics(bufnr, opts, clamp) end end + --- @param buf integer + --- @param diags vim.Diagnostic[] local function add_all_diags(buf, diags) for _, diagnostic in pairs(diags) do add(buf, diagnostic) @@ -417,18 +584,20 @@ local function get_diagnostics(bufnr, opts, clamp) return diagnostics end +--- @param loclist boolean +--- @param opts vim.diagnostic.setqflist.Opts|vim.diagnostic.setloclist.Opts? local function set_list(loclist, opts) opts = opts or {} - local open = vim.F.if_nil(opts.open, true) + local open = if_nil(opts.open, true) local title = opts.title or 'Diagnostics' local winnr = opts.winnr or 0 - local bufnr + local bufnr --- @type integer? if loclist then bufnr = api.nvim_win_get_buf(winnr) end -- Don't clamp line numbers since the quickfix list can already handle line -- numbers beyond the end of the buffer - local diagnostics = get_diagnostics(bufnr, opts, false) + local diagnostics = get_diagnostics(bufnr, opts --[[@as vim.diagnostic.GetOpts]], false) local items = M.toqflist(diagnostics) if loclist then vim.fn.setloclist(winnr, {}, ' ', { title = title, items = items }) @@ -440,10 +609,16 @@ local function set_list(loclist, opts) end end +--- @param position {[1]: integer, [2]: integer} +--- @param search_forward boolean +--- @param bufnr integer +--- @param opts vim.diagnostic.GotoOpts +--- @param namespace integer +--- @return vim.Diagnostic? local function next_diagnostic(position, search_forward, bufnr, opts, namespace) position[1] = position[1] - 1 bufnr = get_bufnr(bufnr) - local wrap = vim.F.if_nil(opts.wrap, true) + local wrap = if_nil(opts.wrap, true) local line_count = api.nvim_buf_line_count(bufnr) local diagnostics = get_diagnostics(bufnr, vim.tbl_extend('keep', opts, { namespace = namespace }), true) @@ -460,6 +635,7 @@ local function next_diagnostic(position, search_forward, bufnr, opts, namespace) end if line_diagnostics[lnum] and not vim.tbl_isempty(line_diagnostics[lnum]) then local line_length = #api.nvim_buf_get_lines(bufnr, lnum, lnum + 1, true)[1] + --- @type function, function local sort_diagnostics, is_next if search_forward then sort_diagnostics = function(a, b) @@ -478,7 +654,9 @@ local function next_diagnostic(position, search_forward, bufnr, opts, namespace) end table.sort(line_diagnostics[lnum], sort_diagnostics) if i == 0 then - for _, v in pairs(line_diagnostics[lnum]) do + for _, v in + pairs(line_diagnostics[lnum] --[[@as table]]) + do if is_next(v) then return v end @@ -490,10 +668,12 @@ local function next_diagnostic(position, search_forward, bufnr, opts, namespace) end end +--- @param opts vim.diagnostic.GotoOpts? +--- @param pos {[1]:integer,[2]:integer}|false local function diagnostic_move_pos(opts, pos) opts = opts or {} - local float = vim.F.if_nil(opts.float, true) + local float = if_nil(opts.float, true) local win_id = opts.win_id or api.nvim_get_current_win() if not pos then @@ -549,8 +729,8 @@ end --- - `table`: Enable this feature with overrides. Use an empty table to use default values. --- - `function`: Function with signature (namespace, bufnr) that returns any of the above. --- ----@param opts table|nil When omitted or "nil", retrieve the current configuration. Otherwise, a ---- configuration table with the following keys: +---@param opts vim.diagnostic.Opts? (table?) When omitted or "nil", retrieve the current +--- configuration. Otherwise, a configuration table with the following keys: --- - underline: (default true) Use underline for diagnostics. Options: --- * severity: Only underline diagnostics matching the given --- severity |diagnostic-severity| @@ -616,17 +796,17 @@ end --- Options: --- * reverse: (boolean) Reverse sort order --- ----@param namespace integer|nil Update the options for the given namespace. When omitted, update the ---- global diagnostic options. +---@param namespace integer? Update the options for the given namespace. When omitted, update the +--- global diagnostic options. --- ----@return table|nil table of current diagnostic config if `opts` is omitted. +---@return vim.diagnostic.Opts? (table?) table of current diagnostic config if `opts` is omitted. function M.config(opts, namespace) vim.validate({ opts = { opts, 't', true }, namespace = { namespace, 'n', true }, }) - local t + local t --- @type vim.diagnostic.Opts if namespace then local ns = M.get_namespace(namespace) t = ns.opts @@ -639,7 +819,9 @@ function M.config(opts, namespace) return vim.deepcopy(t, true) end - for k, v in pairs(opts) do + for k, v in + pairs(opts --[[@as table]]) + do t[k] = v end @@ -662,8 +844,8 @@ end --- ---@param namespace integer The diagnostic namespace ---@param bufnr integer Buffer number ----@param diagnostics table A list of diagnostic items |diagnostic-structure| ----@param opts table|nil Display options to pass to |vim.diagnostic.show()| +---@param diagnostics vim.Diagnostic[] A list of diagnostic items |diagnostic-structure| +---@param opts? vim.diagnostic.Opts (table) Display options to pass to |vim.diagnostic.show()| function M.set(namespace, bufnr, diagnostics, opts) vim.validate({ namespace = { namespace, 'n' }, @@ -689,6 +871,7 @@ function M.set(namespace, bufnr, diagnostics, opts) api.nvim_exec_autocmds('DiagnosticChanged', { modeline = false, buffer = bufnr, + -- TODO(lewis6991): should this be deepcopy()'d like they are in vim.diagnostic.get() data = { diagnostics = diagnostics }, }) end @@ -696,11 +879,11 @@ end --- Get namespace metadata. --- ---@param namespace integer Diagnostic namespace ----@return table Namespace metadata +---@return vim.diagnostic.NS (table) Namespace metadata function M.get_namespace(namespace) vim.validate({ namespace = { namespace, 'n' } }) if not all_namespaces[namespace] then - local name + local name --- @type string? for k, v in pairs(api.nvim_get_namespaces()) do if namespace == v then name = k @@ -721,35 +904,22 @@ end --- Get current diagnostic namespaces. --- ----@return table A list of active diagnostic namespaces |vim.diagnostic|. +---@return table A list of active diagnostic namespaces |vim.diagnostic|. function M.get_namespaces() return vim.deepcopy(all_namespaces, true) end ----@class Diagnostic ----@field bufnr? integer ----@field lnum integer 0-indexed ----@field end_lnum? integer 0-indexed ----@field col integer 0-indexed ----@field end_col? integer 0-indexed ----@field severity? DiagnosticSeverity ----@field message string ----@field source? string ----@field code? string ----@field _tags? { deprecated: boolean, unnecessary: boolean} ----@field user_data? any arbitrary data plugins can add - --- Get current diagnostics. --- --- Modifying diagnostics in the returned table has no effect. To set diagnostics in a buffer, use |vim.diagnostic.set()|. --- ----@param bufnr integer|nil Buffer number to get diagnostics from. Use 0 for +---@param bufnr integer? Buffer number to get diagnostics from. Use 0 for --- current buffer or nil for all buffers. ----@param opts table|nil A table with the following keys: +---@param opts? vim.diagnostic.GetOpts (table) A table with the following keys: --- - namespace: (number) Limit diagnostics to the given namespace. --- - lnum: (number) Limit diagnostics to the given line number. --- - severity: See |diagnostic-severity|. ----@return Diagnostic[] table A list of diagnostic items |diagnostic-structure|. Keys `bufnr`, `end_lnum`, `end_col`, and `severity` are guaranteed to be present. +---@return vim.Diagnostic[] table A list of diagnostic items |diagnostic-structure|. Keys `bufnr`, `end_lnum`, `end_col`, and `severity` are guaranteed to be present. function M.get(bufnr, opts) vim.validate({ bufnr = { bufnr, 'n', true }, @@ -761,12 +931,12 @@ end --- Get current diagnostics count. --- ----@param bufnr integer|nil Buffer number to get diagnostics from. Use 0 for ---- current buffer or nil for all buffers. ----@param opts table|nil A table with the following keys: ---- - namespace: (number) Limit diagnostics to the given namespace. ---- - lnum: (number) Limit diagnostics to the given line number. ---- - severity: See |diagnostic-severity|. +---@param bufnr? integer Buffer number to get diagnostics from. Use 0 for +--- current buffer or nil for all buffers. +---@param opts? table A table with the following keys: +--- - namespace: (number) Limit diagnostics to the given namespace. +--- - lnum: (number) Limit diagnostics to the given line number. +--- - severity: See |diagnostic-severity|. ---@return table A table with actually present severity values as keys (see |diagnostic-severity|) and integer counts as values. function M.count(bufnr, opts) vim.validate({ @@ -775,9 +945,9 @@ function M.count(bufnr, opts) }) local diagnostics = get_diagnostics(bufnr, opts, false) - local count = {} + local count = {} --- @type table for i = 1, #diagnostics do - local severity = diagnostics[i].severity + local severity = diagnostics[i].severity --[[@as integer]] count[severity] = (count[severity] or 0) + 1 end return count @@ -785,8 +955,8 @@ end --- Get the previous diagnostic closest to the cursor position. --- ----@param opts nil|table See |vim.diagnostic.goto_next()| ----@return Diagnostic|nil Previous diagnostic +---@param opts? vim.diagnostic.GotoOpts (table) See |vim.diagnostic.goto_next()| +---@return vim.Diagnostic? Previous diagnostic function M.get_prev(opts) opts = opts or {} @@ -799,9 +969,9 @@ end --- Return the position of the previous diagnostic in the current buffer. --- ----@param opts table|nil See |vim.diagnostic.goto_next()| ----@return table|false Previous diagnostic position as a (row, col) tuple or false if there is no ---- prior diagnostic +---@param opts? vim.diagnostic.GotoOpts (table) See |vim.diagnostic.goto_next()| +---@return table|false: Previous diagnostic position as a (row, col) tuple or false if there is no +--- prior diagnostic function M.get_prev_pos(opts) local prev = M.get_prev(opts) if not prev then @@ -812,15 +982,15 @@ function M.get_prev_pos(opts) end --- Move to the previous diagnostic in the current buffer. ----@param opts table|nil See |vim.diagnostic.goto_next()| +---@param opts? vim.diagnostic.GotoOpts (table) See |vim.diagnostic.goto_next()| function M.goto_prev(opts) return diagnostic_move_pos(opts, M.get_prev_pos(opts)) end --- Get the next diagnostic closest to the cursor position. --- ----@param opts table|nil See |vim.diagnostic.goto_next()| ----@return Diagnostic|nil Next diagnostic +---@param opts? vim.diagnostic.GotoOpts (table) See |vim.diagnostic.goto_next()| +---@return vim.Diagnostic? : Next diagnostic function M.get_next(opts) opts = opts or {} @@ -833,9 +1003,9 @@ end --- Return the position of the next diagnostic in the current buffer. --- ----@param opts table|nil See |vim.diagnostic.goto_next()| ----@return table|false Next diagnostic position as a (row, col) tuple or false if no next ---- diagnostic. +---@param opts? vim.diagnostic.GotoOpts (table) See |vim.diagnostic.goto_next()| +---@return table|false : Next diagnostic position as a (row, col) tuple or false if no next +--- diagnostic. function M.get_next_pos(opts) local next = M.get_next(opts) if not next then @@ -845,10 +1015,21 @@ function M.get_next_pos(opts) return { next.lnum, next.col } end +--- @class vim.diagnostic.GetOpts +--- @field namespace? integer +--- @field lnum? integer +--- @field severity? vim.diagnostic.Severity + +--- @class vim.diagnostic.GotoOpts : vim.diagnostic.GetOpts +--- @field cursor_position? {[1]:integer,[2]:integer} +--- @field wrap? integer +--- @field float? boolean|vim.diagnostic.Opts.Float +--- @field win_id? integer + --- Move to the next diagnostic. --- ----@param opts table|nil Configuration table with the following keys: ---- - namespace: (number) Only consider diagnostics from the given namespace. +---@param opts? vim.diagnostic.GotoOpts (table) Configuration table with the following keys: +--- - namespace: (integer) Only consider diagnostics from the given namespace. --- - cursor_position: (cursor position) Cursor position as a (row, col) tuple. --- See |nvim_win_get_cursor()|. Defaults to the current cursor position. --- - wrap: (boolean, default true) Whether to loop around file or not. Similar to 'wrapscan'. @@ -860,7 +1041,7 @@ end --- the "scope" option). --- - win_id: (number, default 0) Window ID function M.goto_next(opts) - return diagnostic_move_pos(opts, M.get_next_pos(opts)) + diagnostic_move_pos(opts, M.get_next_pos(opts)) end M.handlers.signs = { @@ -885,7 +1066,7 @@ M.handlers.signs = { -- 10 is the default sign priority when none is explicitly specified local priority = opts.signs and opts.signs.priority or 10 - local get_priority + local get_priority --- @type function if opts.severity_sort then if type(opts.severity_sort) == 'table' and opts.severity_sort.reverse then get_priority = function(severity) @@ -951,7 +1132,7 @@ M.handlers.signs = { end end - local text = {} ---@type table + local text = {} ---@type table for k in pairs(M.severity) do if opts.signs.text and opts.signs.text[k] then text[k] = opts.signs.text[k] @@ -975,6 +1156,9 @@ M.handlers.signs = { end end end, + + --- @param namespace integer + --- @param bufnr integer hide = function(namespace, bufnr) local ns = M.get_namespace(namespace) if ns.user_data.sign_ns and api.nvim_buf_is_valid(bufnr) then @@ -1015,10 +1199,12 @@ M.handlers.underline = { local underline_ns = ns.user_data.underline_ns for _, diagnostic in ipairs(diagnostics) do - local higroup = underline_highlight_map[diagnostic.severity] + --- @type string? + local higroup = underline_highlight_map[assert(diagnostic.severity)] if higroup == nil then -- Default to error if we don't have a highlight associated + -- TODO(lewis6991): this is always nil since underline_highlight_map only has integer keys higroup = underline_highlight_map.Error end @@ -1074,7 +1260,7 @@ M.handlers.virtual_text = { return end - local severity + local severity --- @type vim.diagnostic.Severity? if opts.virtual_text then if opts.virtual_text.format then diagnostics = reformat_diagnostics(opts.virtual_text.format, diagnostics) @@ -1132,7 +1318,9 @@ M.handlers.virtual_text = { --- Exported for backward compatibility with --- vim.lsp.diagnostic.get_virtual_text_chunks_for_line(). When that function is eventually removed, --- this can be made local. ----@private +--- @private +--- @param line_diags table +--- @param opts vim.diagnostic.Opts.VirtualText function M._get_virt_text_chunks(line_diags, opts) if #line_diags == 0 then return nil @@ -1182,10 +1370,10 @@ end --- To hide diagnostics and prevent them from re-displaying, use --- |vim.diagnostic.disable()|. --- ----@param namespace integer|nil Diagnostic namespace. When omitted, hide ---- diagnostics from all namespaces. ----@param bufnr integer|nil Buffer number, or 0 for current buffer. When ---- omitted, hide diagnostics in all buffers. +---@param namespace integer? Diagnostic namespace. When omitted, hide +--- diagnostics from all namespaces. +---@param bufnr integer? Buffer number, or 0 for current buffer. When +--- omitted, hide diagnostics in all buffers. function M.hide(namespace, bufnr) vim.validate({ namespace = { namespace, 'n', true }, @@ -1207,11 +1395,11 @@ end --- Check whether diagnostics are disabled in a given buffer. --- ----@param bufnr integer|nil Buffer number, or 0 for current buffer. ----@param namespace integer|nil Diagnostic namespace. When omitted, checks if ---- all diagnostics are disabled in {bufnr}. ---- Otherwise, only checks if diagnostics from ---- {namespace} are disabled. +---@param bufnr integer? Buffer number, or 0 for current buffer. +---@param namespace integer? Diagnostic namespace. When omitted, checks if +--- all diagnostics are disabled in {bufnr}. +--- Otherwise, only checks if diagnostics from +--- {namespace} are disabled. ---@return boolean function M.is_disabled(bufnr, namespace) bufnr = get_bufnr(bufnr) @@ -1228,17 +1416,17 @@ end --- Display diagnostics for the given namespace and buffer. --- ----@param namespace integer|nil Diagnostic namespace. When omitted, show ---- diagnostics from all namespaces. ----@param bufnr integer|nil Buffer number, or 0 for current buffer. When omitted, show ---- diagnostics in all buffers. ----@param diagnostics table|nil The diagnostics to display. When omitted, use the +---@param namespace integer? Diagnostic namespace. When omitted, show +--- diagnostics from all namespaces. +---@param bufnr integer? Buffer number, or 0 for current buffer. When omitted, show +--- diagnostics in all buffers. +---@param diagnostics vim.Diagnostic[]? The diagnostics to display. When omitted, use the --- saved diagnostics for the given namespace and --- buffer. This can be used to display a list of diagnostics --- without saving them or to display only a subset of --- diagnostics. May not be used when {namespace} --- or {bufnr} is nil. ----@param opts table|nil Display options. See |vim.diagnostic.config()|. +---@param opts? vim.diagnostic.Opts (table) Display options. See |vim.diagnostic.config()|. function M.show(namespace, bufnr, diagnostics, opts) vim.validate({ namespace = { namespace, 'n', true }, @@ -1277,24 +1465,24 @@ function M.show(namespace, bufnr, diagnostics, opts) diagnostics = diagnostics or get_diagnostics(bufnr, { namespace = namespace }, true) - if not diagnostics or vim.tbl_isempty(diagnostics) then + if vim.tbl_isempty(diagnostics) then return end - opts = get_resolved_options(opts, namespace, bufnr) + local opts_res = get_resolved_options(opts, namespace, bufnr) - if opts.update_in_insert then + if opts_res.update_in_insert then clear_scheduled_display(namespace, bufnr) else local mode = api.nvim_get_mode() if string.sub(mode.mode, 1, 1) == 'i' then - schedule_display(namespace, bufnr, opts) + schedule_display(namespace, bufnr, opts_res) return end end - if vim.F.if_nil(opts.severity_sort, false) then - if type(opts.severity_sort) == 'table' and opts.severity_sort.reverse then + if if_nil(opts_res.severity_sort, false) then + if type(opts_res.severity_sort) == 'table' and opts_res.severity_sort.reverse then table.sort(diagnostics, function(a, b) return a.severity < b.severity end) @@ -1306,15 +1494,15 @@ function M.show(namespace, bufnr, diagnostics, opts) end for handler_name, handler in pairs(M.handlers) do - if handler.show and opts[handler_name] then - handler.show(namespace, bufnr, diagnostics, opts) + if handler.show and opts_res[handler_name] then + handler.show(namespace, bufnr, diagnostics, opts_res) end end end --- Show diagnostics in a floating window. --- ----@param opts table|nil Configuration table with the same keys +---@param opts vim.diagnostic.Opts.Float? (table?) Configuration table with the same keys --- as |vim.lsp.util.open_floating_preview()| in addition to the following: --- - bufnr: (number) Buffer number to show diagnostics from. --- Defaults to the current buffer. @@ -1354,13 +1542,13 @@ end --- Overrides the setting from |vim.diagnostic.config()|. --- - suffix: Same as {prefix}, but appends the text to the diagnostic instead of --- prepending it. Overrides the setting from |vim.diagnostic.config()|. ----@return integer|nil, integer|nil: ({float_bufnr}, {win_id}) +---@return integer?, integer?: ({float_bufnr}, {win_id}) function M.open_float(opts, ...) -- Support old (bufnr, opts) signature - local bufnr + local bufnr --- @type integer? if opts == nil or type(opts) == 'number' then bufnr = opts - opts = ... + opts = ... --- @type vim.diagnostic.Opts.Float else vim.validate({ opts = { opts, 't', true }, @@ -1382,16 +1570,17 @@ function M.open_float(opts, ...) end local scope = ({ l = 'line', c = 'cursor', b = 'buffer' })[opts.scope] or opts.scope or 'line' - local lnum, col + local lnum, col --- @type integer, integer + local opts_pos = opts.pos if scope == 'line' or scope == 'cursor' then - if not opts.pos then + if not opts_pos then local pos = api.nvim_win_get_cursor(0) lnum = pos[1] - 1 col = pos[2] - elseif type(opts.pos) == 'number' then - lnum = opts.pos - elseif type(opts.pos) == 'table' then - lnum, col = unpack(opts.pos) + elseif type(opts_pos) == 'number' then + lnum = opts_pos + elseif type(opts_pos) == 'table' then + lnum, col = opts_pos[1], opts_pos[2] else error("Invalid value for option 'pos'") end @@ -1399,15 +1588,17 @@ function M.open_float(opts, ...) error("Invalid value for option 'scope'") end - local diagnostics = get_diagnostics(bufnr, opts, true) + local diagnostics = get_diagnostics(bufnr, opts --[[@as vim.diagnostic.GetOpts]], true) if scope == 'line' then + --- @param d vim.Diagnostic diagnostics = vim.tbl_filter(function(d) return d.lnum == lnum end, diagnostics) elseif scope == 'cursor' then -- LSP servers can send diagnostics with `end_col` past the length of the line local line_length = #api.nvim_buf_get_lines(bufnr, lnum, lnum + 1, true)[1] + --- @param d vim.Diagnostic diagnostics = vim.tbl_filter(function(d) return d.lnum == lnum and math.min(d.col, line_length - 1) <= col @@ -1419,7 +1610,7 @@ function M.open_float(opts, ...) return end - local severity_sort = vim.F.if_nil(opts.severity_sort, global_diagnostic_options.severity_sort) + local severity_sort = if_nil(opts.severity_sort, global_diagnostic_options.severity_sort) if severity_sort then if type(severity_sort) == 'table' and severity_sort.reverse then table.sort(diagnostics, function(a, b) @@ -1432,8 +1623,8 @@ function M.open_float(opts, ...) end end - local lines = {} - local highlights = {} + local lines = {} --- @type string[] + local highlights = {} --- @type table[] local header = if_nil(opts.header, 'Diagnostics:') if header then vim.validate({ @@ -1468,7 +1659,7 @@ function M.open_float(opts, ...) return string.format('%d. ', i) end) - local prefix, prefix_hl_group + local prefix, prefix_hl_group --- @type string?, string? if prefix_opt then vim.validate({ prefix = { @@ -1488,7 +1679,7 @@ function M.open_float(opts, ...) return diagnostic.code and string.format(' [%s]', diagnostic.code) or '' end) - local suffix, suffix_hl_group + local suffix, suffix_hl_group --- @type string?, string? if suffix_opt then vim.validate({ suffix = { @@ -1505,15 +1696,18 @@ function M.open_float(opts, ...) end for i, diagnostic in ipairs(diagnostics) do - if prefix_opt and type(prefix_opt) == 'function' then - prefix, prefix_hl_group = prefix_opt(diagnostic, i, #diagnostics) - prefix, prefix_hl_group = prefix or '', prefix_hl_group or 'NormalFloat' + if type(prefix_opt) == 'function' then + --- @cast prefix_opt fun(...): string?, string? + local prefix0, prefix_hl_group0 = prefix_opt(diagnostic, i, #diagnostics) + prefix, prefix_hl_group = prefix0 or '', prefix_hl_group0 or 'NormalFloat' end - if suffix_opt and type(suffix_opt) == 'function' then - suffix, suffix_hl_group = suffix_opt(diagnostic, i, #diagnostics) - suffix, suffix_hl_group = suffix or '', suffix_hl_group or 'NormalFloat' + if type(suffix_opt) == 'function' then + --- @cast suffix_opt fun(...): string?, string? + local suffix0, suffix_hl_group0 = suffix_opt(diagnostic, i, #diagnostics) + suffix, suffix_hl_group = suffix0 or '', suffix_hl_group0 or 'NormalFloat' end - local hiname = floating_highlight_map[diagnostic.severity] + --- @type string? + local hiname = floating_highlight_map[assert(diagnostic.severity)] local message_lines = vim.split(diagnostic.message, '\n') for j = 1, #message_lines do local pre = j == 1 and prefix or string.rep(' ', #prefix) @@ -1561,10 +1755,10 @@ end --- simply remove diagnostic decorations in a way that they can be --- re-displayed, use |vim.diagnostic.hide()|. --- ----@param namespace integer|nil Diagnostic namespace. When omitted, remove ---- diagnostics from all namespaces. ----@param bufnr integer|nil Remove diagnostics for the given buffer. When omitted, ---- diagnostics are removed for all buffers. +---@param namespace integer? Diagnostic namespace. When omitted, remove +--- diagnostics from all namespaces. +---@param bufnr integer? Remove diagnostics for the given buffer. When omitted, +--- diagnostics are removed for all buffers. function M.reset(namespace, bufnr) vim.validate({ namespace = { namespace, 'n', true }, @@ -1591,9 +1785,15 @@ function M.reset(namespace, bufnr) end end +--- @class vim.diagnostic.setqflist.Opts +--- @field namespace? integer +--- @field open? boolean +--- @field title? string +--- @field severity? vim.diagnostic.Severity + --- Add all diagnostics to the quickfix list. --- ----@param opts table|nil Configuration table with the following keys: +---@param opts? vim.diagnostic.setqflist.Opts (table) Configuration table with the following keys: --- - namespace: (number) Only add diagnostics from the given namespace. --- - open: (boolean, default true) Open quickfix list after setting. --- - title: (string) Title of quickfix list. Defaults to "Diagnostics". @@ -1602,9 +1802,16 @@ function M.setqflist(opts) set_list(false, opts) end +--- @class vim.diagnostic.setloclist.Opts +--- @field namespace? integer +--- @field open? boolean +--- @field title? string +--- @field severity? vim.diagnostic.Severity +--- @field winnr? integer + --- Add buffer diagnostics to the location list. --- ----@param opts table|nil Configuration table with the following keys: +---@param opts? vim.diagnostic.setloclist.Opts (table) Configuration table with the following keys: --- - namespace: (number) Only add diagnostics from the given namespace. --- - winnr: (number, default 0) Window number to set location list for. --- - open: (boolean, default true) Open the location list after setting. @@ -1616,9 +1823,9 @@ end --- Disable diagnostics in the given buffer. --- ----@param bufnr integer|nil Buffer number, or 0 for current buffer. When ---- omitted, disable diagnostics in all buffers. ----@param namespace integer|nil Only disable diagnostics for the given namespace. +---@param bufnr integer? Buffer number, or 0 for current buffer. When +--- omitted, disable diagnostics in all buffers. +---@param namespace integer? Only disable diagnostics for the given namespace. function M.disable(bufnr, namespace) vim.validate({ bufnr = { bufnr, 'n', true }, namespace = { namespace, 'n', true } }) if bufnr == nil then @@ -1653,9 +1860,9 @@ end --- Enable diagnostics in the given buffer. --- ----@param bufnr integer|nil Buffer number, or 0 for current buffer. When ---- omitted, enable diagnostics in all buffers. ----@param namespace integer|nil Only enable diagnostics for the given namespace. +---@param bufnr integer? Buffer number, or 0 for current buffer. When +--- omitted, enable diagnostics in all buffers. +---@param namespace integer? Only enable diagnostics for the given namespace. function M.enable(bufnr, namespace) vim.validate({ bufnr = { bufnr, 'n', true }, namespace = { namespace, 'n', true } }) if bufnr == nil then @@ -1701,14 +1908,14 @@ end --- ---@param str string String to parse diagnostics from. ---@param pat string Lua pattern with capture groups. ----@param groups table List of fields in a |diagnostic-structure| to +---@param groups string[] List of fields in a |diagnostic-structure| to --- associate with captures from {pat}. ---@param severity_map table A table mapping the severity field from {groups} --- with an item from |vim.diagnostic.severity|. ----@param defaults table|nil Table of default values for any fields not listed in {groups}. ---- When omitted, numeric values default to 0 and "severity" defaults to ---- ERROR. ----@return Diagnostic|nil: |diagnostic-structure| or `nil` if {pat} fails to match {str}. +---@param defaults table? Table of default values for any fields not listed in {groups}. +--- When omitted, numeric values default to 0 and "severity" defaults to +--- ERROR. +---@return vim.Diagnostic?: |diagnostic-structure| or `nil` if {pat} fails to match {str}. function M.match(str, pat, groups, severity_map, defaults) vim.validate({ str = { str, 's' }, @@ -1718,14 +1925,16 @@ function M.match(str, pat, groups, severity_map, defaults) defaults = { defaults, 't', true }, }) + --- @type table severity_map = severity_map or M.severity - local diagnostic = {} - local matches = { string.match(str, pat) } + local matches = { str:match(pat) } --- @type any[] if vim.tbl_isempty(matches) then return end + local diagnostic = {} --- @type type + for i, match in ipairs(matches) do local field = groups[i] if field == 'severity' then @@ -1733,10 +1942,10 @@ function M.match(str, pat, groups, severity_map, defaults) elseif field == 'lnum' or field == 'end_lnum' or field == 'col' or field == 'end_col' then match = assert(tonumber(match)) - 1 end - diagnostic[field] = match + diagnostic[field] = match --- @type any end - diagnostic = vim.tbl_extend('keep', diagnostic, defaults or {}) + diagnostic = vim.tbl_extend('keep', diagnostic, defaults or {}) --- @type vim.Diagnostic diagnostic.severity = diagnostic.severity or M.severity.ERROR diagnostic.col = diagnostic.col or 0 diagnostic.end_lnum = diagnostic.end_lnum or diagnostic.lnum @@ -1754,7 +1963,7 @@ local errlist_type_map = { --- Convert a list of diagnostics to a list of quickfix items that can be --- passed to |setqflist()| or |setloclist()|. --- ----@param diagnostics table List of diagnostics |diagnostic-structure|. +---@param diagnostics vim.Diagnostic[] List of diagnostics |diagnostic-structure|. ---@return table[] of quickfix list items |setqflist-what| function M.toqflist(diagnostics) vim.validate({ @@ -1765,7 +1974,7 @@ function M.toqflist(diagnostics) }, }) - local list = {} + local list = {} --- @type table[] for _, v in ipairs(diagnostics) do local item = { bufnr = v.bufnr, @@ -1795,7 +2004,7 @@ end --- Convert a list of quickfix items to a list of diagnostics. --- ---@param list table[] List of quickfix items from |getqflist()| or |getloclist()|. ----@return Diagnostic[] array of |diagnostic-structure| +---@return vim.Diagnostic[] array of |diagnostic-structure| function M.fromqflist(list) vim.validate({ list = { @@ -1805,7 +2014,7 @@ function M.fromqflist(list) }, }) - local diagnostics = {} + local diagnostics = {} --- @type vim.Diagnostic[] for _, item in ipairs(list) do if item.valid == 1 then local lnum = math.max(0, item.lnum - 1) @@ -1813,7 +2022,7 @@ function M.fromqflist(list) local end_lnum = item.end_lnum > 0 and (item.end_lnum - 1) or lnum local end_col = item.end_col > 0 and (item.end_col - 1) or col local severity = item.type ~= '' and M.severity[item.type] or M.severity.ERROR - table.insert(diagnostics, { + diagnostics[#diagnostics + 1] = { bufnr = item.bufnr, lnum = lnum, col = col, @@ -1821,7 +2030,7 @@ function M.fromqflist(list) end_col = end_col, severity = severity, message = item.text, - }) + } end end return diagnostics -- cgit From 463cb28a22237e20d603edd55088c41795a4e0c5 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Sun, 7 Jan 2024 10:08:51 +0100 Subject: docs(column): 'statuscolumn' redraw interaction with 'relativenumber' --- runtime/lua/vim/_meta/options.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 7ad720b6b2..b598b2c99a 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -6373,6 +6373,9 @@ vim.go.sol = vim.go.startofline --- when drawing the actual buffer line, and positive when --- drawing the wrapped part of a buffer line. --- +--- When using `v:relnum`, keep in mind that cursor movement by itself will +--- not cause the 'statuscolumn' to update unless `'relativenumber'` is set. +--- --- NOTE: The %@ click execute function item is supported as well but the --- specified function will be the same for each row in the same column. --- It cannot be switched out through a dynamic 'statuscolumn' format, the -- cgit From 91dc04a5e12a3d0c5be56768ded5971bc80e6f8e Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Tue, 16 Jan 2024 17:45:57 +0000 Subject: vim-patch:9.1.0013: Modula2 filetype support lacking (#27020) Problem: Modula2 filetype support lacking Solution: Improve the Modula-2 runtime support, add additional modula2 dialects, add compiler plugin, update syntax highlighting, include syntax tests, update Makefiles (Doug Kearns) closes: vim/vim#6796 closes: vim/vim#8115 https://github.com/vim/vim/commit/68a89470693c7687d4e736ca056c05de632e3ac7 - Luaify the detection script: - Split the `(*!m2foo*)` and `(*!m2foo+bar*)` detection into two Lua patterns, as Lua capture groups cannot be used with `?` and friends (as they only work on character classes). - Use `vim.api.nvim_buf_call()` (ew) to call `modula2#SetDialect()` to ensure `b:modula2` is set for the given bufnr. - Skip the syntax screendump tests. (A shame as they test some of the detection from `(*!m2foo+bar*)` tags, but I tested this locally and it seems to work) - Port the synmenu.vim changes from Vim9 script. (Also tested this locally) - (And also add the missing comma for `b:browsefilter` from earlier.) Co-authored-by: Doug Kearns --- runtime/lua/vim/filetype.lua | 4 +-- runtime/lua/vim/filetype/detect.lua | 55 +++++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 5 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 8cd5f19569..a83c74fd7c 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -341,7 +341,7 @@ local extension = { decl = detect.decl, dec = detect.decl, dcl = detect_seq(detect.decl, 'clean'), - def = 'def', + def = detect.def, desc = 'desc', directory = 'desktop', desktop = 'desktop', @@ -674,8 +674,6 @@ local extension = { mmp = 'mmp', mms = detect.mms, DEF = 'modula2', - m2 = 'modula2', - mi = 'modula2', lm3 = 'modula3', mojo = 'mojo', ['🔥'] = 'mojo', -- 🙄 diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua index 6a14c73c92..ce3b873e40 100644 --- a/runtime/lua/vim/filetype/detect.lua +++ b/runtime/lua/vim/filetype/detect.lua @@ -419,6 +419,55 @@ function M.dtrace(_, bufnr) return 'd' end +--- @param bufnr integer +--- @return boolean +local function is_modula2(bufnr) + return matchregex(nextnonblank(bufnr, 1), [[\ Date: Sun, 14 Jan 2024 23:12:54 -0500 Subject: refactor(lsp): deprecate `vim.lsp.util.lookup_section` This function is used only in the `workspace/configuration` handler, and does not warrant a public API because of its confusing return types. The only caller `vim.lsp.handlers["workspace.configuration"]` is also refactored to use `vim.tbl_get()` instead. --- runtime/lua/vim/lsp/handlers.lua | 17 ++++++++++++++--- runtime/lua/vim/lsp/util.lua | 2 ++ 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index daf09b6430..6ed8e1d40f 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -170,6 +170,14 @@ M[ms.workspace_applyEdit] = function(_, workspace_edit, ctx) } end +---@param table table e.g., { foo = { bar = "z" } } +---@param section string indicating the field of the table, e.g., "foo.bar" +---@return any|nil setting value read from the table, or `nil` not found +local function lookup_section(table, section) + local keys = vim.split(section, '.', { plain = true }) --- @type string[] + return vim.tbl_get(table, unpack(keys)) +end + --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_configuration M[ms.workspace_configuration] = function(_, result, ctx) local client_id = ctx.client_id @@ -189,10 +197,13 @@ M[ms.workspace_configuration] = function(_, result, ctx) local response = {} for _, item in ipairs(result.items) do if item.section then - local value = util.lookup_section(client.config.settings, item.section) + local value = lookup_section(client.config.settings, item.section) -- For empty sections with no explicit '' key, return settings as is - if value == vim.NIL and item.section == '' then - value = client.config.settings or vim.NIL + if value == nil and item.section == '' then + value = client.config.settings + end + if value == nil then + value = vim.NIL end table.insert(response, value) end diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 50890e37ce..cee09d85e0 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -2140,7 +2140,9 @@ end ---@param settings table language server settings ---@param section string indicating the field of the settings table ---@return table|string|vim.NIL The value of settings accessed via section. `vim.NIL` if not found. +---@deprecated function M.lookup_section(settings, section) + vim.deprecate('vim.lsp.util.lookup_section()', 'vim.tbl_get() with `vim.split`', '0.12') for part in vim.gsplit(section, '.', { plain = true }) do settings = settings[part] if settings == nil then -- cgit From b3e5587b7f1cd6206240aea38740d2205c10ae34 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 17 Jan 2024 07:01:39 +0100 Subject: docs: various fixes (#26929) Co-authored-by: Patrick Bollinger Co-authored-by: vilo1839 <139687192+vilo1839@users.noreply.github.com> --- runtime/lua/vim/_meta/options.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index b598b2c99a..8c550fccdb 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -6362,7 +6362,7 @@ vim.go.sol = vim.go.startofline --- The 'statuscolumn' width follows that of the default columns and --- adapts to the `'numberwidth'`, `'signcolumn'` and `'foldcolumn'` option --- values (regardless of whether the sign and fold items are present). ---- Aditionally, the 'statuscolumn' grows with the size of the evaluated +--- Additionally, the 'statuscolumn' grows with the size of the evaluated --- format string, up to a point (following the maximum size of the default --- fold, sign and number columns). Shrinking only happens when the number --- of lines in a buffer changes, or the 'statuscolumn' option is set. -- cgit From 14b7ffcf89bc448b626df3d9e19f9f5a3682ae2b Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 16 Jan 2024 10:30:08 +0000 Subject: feat: add __call typing for vim.inspect() --- runtime/lua/vim/_editor.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 4fe601dfd5..52a21587f4 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -190,12 +190,18 @@ function vim._os_proc_children(ppid) return children end +--- @class vim.inspect.Opts +--- @field depth? integer +--- @field newline? string +--- @field process? fun(item:any, path: string[]): any + --- Gets a human-readable representation of the given object. --- ---@see |vim.print()| ---@see https://github.com/kikito/inspect.lua ---@see https://github.com/mpeterv/vinspect ---@return string +---@overload fun(x: any, opts?: vim.inspect.Opts): string vim.inspect = vim.inspect do -- cgit From 5aa14e1231b7eccfbc54cba8f20d54105212847d Mon Sep 17 00:00:00 2001 From: altermo <107814000+altermo@users.noreply.github.com> Date: Wed, 17 Jan 2024 20:34:25 +0100 Subject: fix(lua): return after assert returns assert message (#27064) --- runtime/lua/vim/diagnostic.lua | 6 ++---- runtime/lua/vim/glob.lua | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index c7a1e8ebd3..03a1fe9a2f 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -180,10 +180,8 @@ local all_namespaces = {} ---@return vim.diagnostic.Severity? local function to_severity(severity) if type(severity) == 'string' then - return assert( - M.severity[string.upper(severity)], - string.format('Invalid severity: %s', severity) - ) + assert(M.severity[string.upper(severity)], string.format('Invalid severity: %s', severity)) + return M.severity[string.upper(severity)] end return severity end diff --git a/runtime/lua/vim/glob.lua b/runtime/lua/vim/glob.lua index 49d6f555da..764200dd36 100644 --- a/runtime/lua/vim/glob.lua +++ b/runtime/lua/vim/glob.lua @@ -77,7 +77,8 @@ function M.to_lpeg(pattern) }) local lpeg_pattern = p:match(pattern) --[[@as vim.lpeg.Pattern?]] - return assert(lpeg_pattern, 'Invalid glob') + assert(lpeg_pattern, 'Invalid glob') + return lpeg_pattern end return M -- cgit From 780dd88b68b7a4d97c8b7ec6a8d33ab523ab04dd Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 18 Jan 2024 07:14:12 +0800 Subject: vim-patch:9.1.0039: too vague errors for 'listchars'/'fillchars' (#27070) Problem: too vague errors for 'listchars'/'fillchars' Solution: Include the field name in error message. (zeertzjq) related: #27050 closes: vim/vim#13877 https://github.com/vim/vim/commit/6a8d2e1634f8f0d7463a2786dbcbe0f38dd287a7 Co-authored-by: Cole Frankenhoff --- runtime/lua/vim/_meta/options.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 8c550fccdb..c9e2e302dc 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -2197,7 +2197,7 @@ vim.bo.ft = vim.bo.filetype --- Characters to fill the statuslines, vertical separators and special --- lines in the window. --- It is a comma-separated list of items. Each item has a name, a colon ---- and the value of that item: +--- and the value of that item: `E1511` --- --- item default Used for ~ --- stl ' ' statusline of the current window @@ -2238,7 +2238,7 @@ vim.bo.ft = vim.bo.filetype --- --- For the "stl", "stlnc", "foldopen", "foldclose" and "foldsep" items --- single-byte and multibyte characters are supported. But double-width ---- characters are not supported. +--- characters are not supported. `E1512` --- --- The highlighting used for these items: --- item highlight group ~ @@ -3829,7 +3829,7 @@ vim.o.list = false vim.wo.list = vim.o.list --- Strings to use in 'list' mode and for the `:list` command. It is a ---- comma-separated list of string settings. +--- comma-separated list of string settings. *E1511* --- --- *lcs-eol* --- eol:c Character to show at the end of each line. When @@ -3921,7 +3921,7 @@ vim.wo.list = vim.o.list --- omitted. --- --- The characters ':' and ',' should not be used. UTF-8 characters can ---- be used. All characters must be single width. +--- be used. All characters must be single width. *E1512* --- --- Each character can be specified as hex: --- -- cgit From 95cbedaa1798a7c1489b68dd60380a41443ed34b Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 18 Jan 2024 00:14:48 -0800 Subject: docs: various #25289 Co-authored-by: Jongwook Choi Co-authored-by: Oliver Marriott Co-authored-by: Benoit de Chezelles Co-authored-by: Jongwook Choi --- runtime/lua/vim/lsp.lua | 17 ++++++++--------- runtime/lua/vim/lsp/inlay_hint.lua | 8 +++++++- 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index a02a93d559..f3448209ba 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -488,8 +488,7 @@ end --- See |vim.lsp.start_client()| for all available options. The most important are: --- --- - `name` arbitrary name for the LSP client. Should be unique per language server. ---- - `cmd` command (in list form) used to start the language server. Must be absolute, or found on ---- `$PATH`. Shell constructs like `~` are not expanded. +--- - `cmd` command string[] or function, described at |vim.lsp.start_client()|. --- - `root_dir` path to the project root. By default this is used to decide if an existing client --- should be re-used. The example above uses |vim.fs.find()| and |vim.fs.dirname()| to detect the --- root by traversing the file system upwards starting from the current directory until either @@ -666,13 +665,13 @@ end --- Field `cmd` in {config} is required. --- ---@param config (lsp.ClientConfig) Configuration for the server: ---- - cmd: (string[]|fun(dispatchers: table):table) command a list of ---- strings treated like |jobstart()|. The command must launch the language server ---- process. `cmd` can also be a function that creates an RPC client. ---- The function receives a dispatchers table and must return a table with the ---- functions `request`, `notify`, `is_closing` and `terminate` ---- See |vim.lsp.rpc.request()| and |vim.lsp.rpc.notify()| ---- For TCP there is a built-in rpc client factory: |vim.lsp.rpc.connect()| +--- - cmd: (string[]|fun(dispatchers: table):table) command string[] that launches the language +--- server (treated as in |jobstart()|, must be absolute or on `$PATH`, shell constructs like +--- "~" are not expanded), or function that creates an RPC client. Function receives +--- a `dispatchers` table and returns a table with member functions `request`, `notify`, +--- `is_closing` and `terminate`. +--- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|. +--- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()| --- --- - cmd_cwd: (string, default=|getcwd()|) Directory to launch --- the `cmd` process. Not related to `root_dir`. diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua index ce1680549e..4816b873ba 100644 --- a/runtime/lua/vim/lsp/inlay_hint.lua +++ b/runtime/lua/vim/lsp/inlay_hint.lua @@ -368,7 +368,13 @@ function M.is_enabled(bufnr) return bufstates[bufnr] and bufstates[bufnr].enabled or false end ---- Enable/disable/toggle inlay hints for a buffer +--- Enables or disables inlay hints for a buffer. +--- +--- To "toggle", pass the inverse of `is_enabled()`: +--- +--- ```lua +--- vim.lsp.inlay_hint.enable(0, not vim.lsp.inlay_hint.is_enabled()) +--- ``` --- --- @param bufnr (integer|nil) Buffer handle, or 0 or nil for current --- @param enable (boolean|nil) true/nil to enable, false to disable -- cgit From ab3a7fc3e3c0166f5792526699f035dd9e057ee9 Mon Sep 17 00:00:00 2001 From: notomo Date: Thu, 18 Jan 2024 22:01:57 +0900 Subject: docs(vim.iter): correct `bool` to `boolean` (#27018) --- runtime/lua/vim/iter.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index a63d5ba565..d720745110 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -181,7 +181,7 @@ end --- local bufs = vim.iter(vim.api.nvim_list_bufs()):filter(vim.api.nvim_buf_is_loaded) --- ``` --- ----@param f fun(...):bool Takes all values returned from the previous stage +---@param f fun(...):boolean Takes all values returned from the previous stage --- in the pipeline and returns false or nil if the --- current iterator element should be removed. ---@return Iter @@ -884,7 +884,7 @@ end --- Returns true if any of the items in the iterator match the given predicate. --- ----@param pred fun(...):bool Predicate function. Takes all values returned from the previous +---@param pred fun(...):boolean Predicate function. Takes all values returned from the previous --- stage in the pipeline as arguments and returns true if the --- predicate matches. function Iter.any(self, pred) @@ -908,7 +908,7 @@ end --- Returns true if all items in the iterator match the given predicate. --- ----@param pred fun(...):bool Predicate function. Takes all values returned from the previous +---@param pred fun(...):boolean Predicate function. Takes all values returned from the previous --- stage in the pipeline as arguments and returns true if the --- predicate matches. function Iter.all(self, pred) @@ -1106,7 +1106,7 @@ end --- ---@see |Iter:filter()| --- ----@param f fun(...):bool Filter function. Accepts the current iterator or table values as +---@param f fun(...):boolean Filter function. Accepts the current iterator or table values as --- arguments and returns true if those values should be kept in the --- final table ---@param src table|function Table or iterator function to filter -- cgit From 674f2513d4d43688a55913456e6c01ddacceb199 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Thu, 18 Jan 2024 15:12:03 +0100 Subject: fix(treesitter): validate language alias for injections Problem: Parsed language annotations can be random garbage so `nvim_get_runtime_file` throws an error. Solution: Validate that `alias` is a valid language name before trying to find a parser for it. --- runtime/lua/vim/treesitter/languagetree.lua | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index a249a10f47..971c4449e8 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -757,6 +757,11 @@ end) ---@param alias string language or filetype name ---@return string? # resolved parser name local function resolve_lang(alias) + -- validate that `alias` is a legal language + if not (alias and alias:match('[%w_]+') == alias) then + return + end + if has_parser(alias) then return alias end -- cgit From 2645c9d576e430e62b60d1902d4a6b887e46a670 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Wed, 17 Jan 2024 15:55:00 +0100 Subject: docs(extmarks): add undocumented "details" array fields --- runtime/lua/vim/_meta/api.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 3f06d4fd43..f773ddd75c 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -323,8 +323,8 @@ function vim.api.nvim_buf_get_commands(buffer, opts) end --- @return integer[] function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end ---- Gets `extmarks` (including `signs`) in "traversal order" from a `charwise` ---- region defined by buffer positions (inclusive, 0-indexed `api-indexing`). +--- Gets `extmarks` in "traversal order" from a `charwise` region defined by +--- buffer positions (inclusive, 0-indexed `api-indexing`). --- Region can be given as (row,col) tuples, or valid extmark ids (whose --- positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1) --- respectively, thus the following are equivalent: @@ -339,6 +339,9 @@ function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end --- Note: when using extmark ranges (marks with a end_row/end_col position) --- the `overlap` option might be useful. Otherwise only the start position of --- an extmark will be considered. +--- Note: legacy signs placed through the `:sign` commands are implemented as +--- extmarks and will show up here. Their details array will contain a +--- `sign_name` field. --- Example: --- --- ```lua @@ -567,7 +570,9 @@ function vim.api.nvim_buf_line_count(buffer) end --- text around the mark was deleted and then restored by --- undo. Defaults to true. --- • invalidate : boolean that indicates whether to hide the ---- extmark if the entirety of its range is deleted. If +--- extmark if the entirety of its range is deleted. For +--- hidden marks, an "invalid" key is added to the "details" +--- array of `nvim_buf_get_extmarks()` and family. If --- "undo_restore" is false, the extmark is deleted instead. --- • priority: a priority value for the highlight group or sign --- attribute. For example treesitter highlighting uses a -- cgit From 9707363b09dbadeb58966d6d45acca17bd74e527 Mon Sep 17 00:00:00 2001 From: altermo Date: Thu, 18 Jan 2024 10:02:35 +0100 Subject: refactor(lua): refactored glob --- runtime/lua/vim/glob.lua | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/glob.lua b/runtime/lua/vim/glob.lua index 764200dd36..ad4a915a94 100644 --- a/runtime/lua/vim/glob.lua +++ b/runtime/lua/vim/glob.lua @@ -1,7 +1,11 @@ local lpeg = vim.lpeg +local P, S, V, R, B = lpeg.P, lpeg.S, lpeg.V, lpeg.R, lpeg.B +local C, Cc, Ct, Cf = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cf local M = {} +local pathsep = P('/') + --- Parses a raw glob into an |lua-lpeg| pattern. --- --- This uses glob semantics from LSP 3.17.0: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern @@ -17,18 +21,8 @@ local M = {} ---@param pattern string The raw glob pattern ---@return vim.lpeg.Pattern pattern An |lua-lpeg| representation of the pattern function M.to_lpeg(pattern) - local l = lpeg - - local P, S, V = lpeg.P, lpeg.S, lpeg.V - local C, Cc, Ct, Cf = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cf - - local pathsep = '/' - local function class(inv, ranges) - for i, r in ipairs(ranges) do - ranges[i] = r[1] .. r[2] - end - local patt = l.R(unpack(ranges)) + local patt = R(unpack(vim.tbl_map(table.concat, ranges))) if inv == '!' then patt = P(1) - patt end @@ -44,11 +38,11 @@ function M.to_lpeg(pattern) end local function star(stars, after) - return (-after * (l.P(1) - pathsep)) ^ #stars * after + return (-after * (P(1) - pathsep)) ^ #stars * after end local function dstar(after) - return (-after * l.P(1)) ^ 0 * after + return (-after * P(1)) ^ 0 * after end local p = P({ @@ -59,11 +53,17 @@ function M.to_lpeg(pattern) * (V('Elem') + V('End')), mul ), - DStar = P('**') * (P(pathsep) * (V('Elem') + V('End')) + V('End')) / dstar, + DStar = (B(pathsep) + -B(P(1))) + * P('**') + * (pathsep * (V('Elem') + V('End')) + V('End')) + / dstar, Star = C(P('*') ^ 1) * (V('Elem') + V('End')) / star, - Ques = P('?') * Cc(l.P(1) - pathsep), - Class = P('[') * C(P('!') ^ -1) * Ct(Ct(C(1) * '-' * C(P(1) - ']')) ^ 1 * ']') / class, - CondList = P('{') * Cf(V('Cond') * (P(',') * V('Cond')) ^ 0, add) * '}', + Ques = P('?') * Cc(P(1) - pathsep), + Class = P('[') + * C(P('!') ^ -1) + * Ct(Ct(C(P(1)) * P('-') * C(P(1) - P(']'))) ^ 1 * P(']')) + / class, + CondList = P('{') * Cf(V('Cond') * (P(',') * V('Cond')) ^ 0, add) * P('}'), -- TODO: '*' inside a {} condition is interpreted literally but should probably have the same -- wildcard semantics it usually has. -- Fixing this is non-trivial because '*' should match non-greedily up to "the rest of the @@ -71,9 +71,9 @@ function M.to_lpeg(pattern) -- condition means "everything after the {}" where several other options separated by ',' may -- exist in between that should not be matched by '*'. Cond = Cf((V('Ques') + V('Class') + V('CondList') + (V('Literal') - S(',}'))) ^ 1, mul) - + Cc(l.P(0)), - Literal = P(1) / l.P, - End = P(-1) * Cc(l.P(-1)), + + Cc(P(0)), + Literal = P(1) / P, + End = P(-1) * Cc(P(-1)), }) local lpeg_pattern = p:match(pattern) --[[@as vim.lpeg.Pattern?]] -- cgit From 5a8fe0769cc9c5d8323b073d5c45ee37ce91c049 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Mon, 15 Jan 2024 14:19:34 -0500 Subject: fix(vim.deprecate): show deprecation warning in devel versions as well Problem: On devel(nightly) versions, deprecation warnings for hard-deprecated features are not being displayed. E.g., - to be removed in: 0.11 - hard-deprecation since 0.10 - soft-deprecation since 0.9 then 0.10-nightly (0.10.0-dev) versions as well as 0.10.0 (stable) should display the deprecation warning message. Solution: Improve the code and logic on `vim.deprecate()`, and improve test cases with mocked `vim.version()`. --- runtime/lua/vim/_editor.lua | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 52a21587f4..fd49f63558 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -1033,21 +1033,44 @@ end --- ---@return string|nil # Deprecated message, or nil if no message was shown. function vim.deprecate(name, alternative, version, plugin, backtrace) + vim.validate { + name = { name, 'string' }, + alternative = { alternative, 'string', true }, + version = { version, 'string', true }, + plugin = { plugin, 'string', true }, + } + plugin = plugin or 'Nvim' + -- Only issue warning if feature is hard-deprecated as specified by MAINTAIN.md. - if plugin == nil then - local current_version = vim.version() - local deprecated_version = assert(vim.version.parse(version)) - local soft_deprecated_version = - { deprecated_version.major, deprecated_version.minor - 1, deprecated_version.patch } - local deprecate = vim.version.lt(current_version, soft_deprecated_version) - if deprecate then + -- e.g., when planned to be removed in version = '0.12' (soft-deprecated since 0.10-dev), + -- show warnings since 0.11, including 0.11-dev (hard_deprecated_since = 0.11-dev). + if plugin == 'Nvim' then + local current_version = vim.version() ---@type Version + local removal_version = assert(vim.version.parse(version)) + local is_hard_deprecated ---@type boolean + + if removal_version.minor > 0 then + local hard_deprecated_since = assert(vim.version._version({ + major = removal_version.major, + minor = removal_version.minor - 1, + patch = 0, + prerelease = 'dev', -- Show deprecation warnings in devel (nightly) version as well + })) + is_hard_deprecated = (current_version >= hard_deprecated_since) + else + -- Assume there will be no next minor version before bumping up the major version; + -- therefore we can always show a warning. + assert(removal_version.minor == 0, vim.inspect(removal_version)) + is_hard_deprecated = true + end + + if not is_hard_deprecated then return end end local msg = ('%s is deprecated'):format(name) - plugin = plugin or 'Nvim' - msg = alternative and ('%s, use %s instead.'):format(msg, alternative) or msg + msg = alternative and ('%s, use %s instead.'):format(msg, alternative) or (msg .. '.') msg = ('%s%s\nThis feature will be removed in %s version %s'):format( msg, (plugin == 'Nvim' and ' :help deprecated' or ''), -- cgit From fa9a85ae468b9df30ae9e5c05a08c0f124e267df Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Tue, 16 Jan 2024 19:19:21 -0500 Subject: fix(lsp): clean up duplicate and unused meta type annotations --- runtime/lua/vim/lsp/_meta.lua | 7 ------- runtime/lua/vim/lsp/_meta/protocol.lua | 13 +++++++------ 2 files changed, 7 insertions(+), 13 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/_meta.lua b/runtime/lua/vim/lsp/_meta.lua index 559939c236..be3222828d 100644 --- a/runtime/lua/vim/lsp/_meta.lua +++ b/runtime/lua/vim/lsp/_meta.lua @@ -14,10 +14,3 @@ error('Cannot require a meta file') ---@field code integer ---@field message string ---@field data string|number|boolean|table[]|table|nil - ---- @class lsp.DocumentFilter ---- @field language? string ---- @field scheme? string ---- @field pattern? string - ---- @alias lsp.RegisterOptions any | lsp.StaticRegistrationOptions | lsp.TextDocumentRegistrationOptions diff --git a/runtime/lua/vim/lsp/_meta/protocol.lua b/runtime/lua/vim/lsp/_meta/protocol.lua index 4c053cb57e..b897b6bba5 100644 --- a/runtime/lua/vim/lsp/_meta/protocol.lua +++ b/runtime/lua/vim/lsp/_meta/protocol.lua @@ -1,7 +1,11 @@ --[[ -This file is autogenerated from scripts/gen_lsp.lua +THIS FILE IS GENERATED by scripts/gen_lsp.lua +DO NOT EDIT MANUALLY + +Based on LSP protocol 3.18 + Regenerate: -nvim -l scripts/gen_lsp.lua gen --version 3.18 --out runtime/lua/vim/lsp/_meta/protocol.lua +nvim -l scripts/gen_lsp.lua gen --version 3.18 --]] ---@meta @@ -9,12 +13,9 @@ error('Cannot require a meta file') ---@alias lsp.null nil ---@alias uinteger integer ----@alias lsp.decimal number +---@alias decimal number ---@alias lsp.DocumentUri string ---@alias lsp.URI string ----@alias lsp.LSPObject table ----@alias lsp.LSPArray lsp.LSPAny[] ----@alias lsp.LSPAny lsp.LSPObject|lsp.LSPArray|string|number|boolean|nil ---@class lsp.ImplementationParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams -- cgit From 646fdf1073433e2bdeec3433f6cbdf8f4be37098 Mon Sep 17 00:00:00 2001 From: glepnir Date: Wed, 17 Jan 2024 20:14:26 +0800 Subject: refactor(api): use hl id directly in nvim_buf_set_extmark --- runtime/lua/vim/_meta/api_keysets.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index bb1031b2fa..377060256a 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -246,7 +246,7 @@ error('Cannot require a meta file') --- @field end_line? integer --- @field end_row? integer --- @field end_col? integer ---- @field hl_group? any +--- @field hl_group? integer --- @field virt_text? any[] --- @field virt_text_pos? string --- @field virt_text_win_col? integer @@ -264,10 +264,10 @@ error('Cannot require a meta file') --- @field virt_lines_leftcol? boolean --- @field strict? boolean --- @field sign_text? string ---- @field sign_hl_group? any ---- @field number_hl_group? any ---- @field line_hl_group? any ---- @field cursorline_hl_group? any +--- @field sign_hl_group? integer +--- @field number_hl_group? integer +--- @field line_hl_group? integer +--- @field cursorline_hl_group? integer --- @field conceal? string --- @field spell? boolean --- @field ui_watched? boolean -- cgit From c75af76b7191833696d972c6cddc48f6681c96a3 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 20 Jan 2024 10:35:45 +0100 Subject: vim-patch:27a4632af675 runtime(filetype): detect *.ck files as Chuck filetype (vim/vim#13888) closes vim/vim#13886 https://github.com/vim/vim/commit/27a4632af675345f9d3b4f3d66a63756835df8cc Co-authored-by: Christian Brabandt --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index a83c74fd7c..7e1803f640 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -267,6 +267,7 @@ local extension = { crdpro = 'chordpro', cho = 'chordpro', chordpro = 'chordpro', + ck = 'chuck', eni = 'cl', icl = 'clean', cljx = 'clojure', -- cgit From fa4b02fa67e5d04e37de7c767f811d497a72f95e Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Mon, 15 Jan 2024 12:13:09 -0500 Subject: feat(vim.version): add `vim.version.le` and `vim.version.ge` - Problem: One cannot easily write something like, for example: `version_current >= {0, 10, 0}`; writing like `not vim.version.lt(version_current, {0, 10, 0})` is verbose. - Solution: add {`le`,`ge`} in addition to {`lt`,`gt`}. - Also improve typing on the operator methods: allow `string` as well. - Update the example in `vim.version.range()` docs: `ge` in place of `gt` better matches the semantics of `range:has`. --- runtime/lua/vim/version.lua | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua index 0873402e29..4f52938c6e 100644 --- a/runtime/lua/vim/version.lua +++ b/runtime/lua/vim/version.lua @@ -259,11 +259,12 @@ end --- print(r:has(vim.version())) -- check against current Nvim version --- ``` --- ---- Or use cmp(), eq(), lt(), and gt() to compare `.to` and `.from` directly: +--- Or use cmp(), le(), lt(), ge(), gt(), and/or eq() to compare a version +--- against `.to` and `.from` directly: --- --- ```lua ---- local r = vim.version.range('1.0.0 - 2.0.0') ---- print(vim.version.gt({1,0,3}, r.from) and vim.version.lt({1,0,3}, r.to)) +--- local r = vim.version.range('1.0.0 - 2.0.0') -- >=1.0, <2.0 +--- print(vim.version.ge({1,0,3}, r.from) and vim.version.lt({1,0,3}, r.to)) --- ``` --- --- @see # https://github.com/npm/node-semver#ranges @@ -364,8 +365,8 @@ end --- --- @note Per semver, build metadata is ignored when comparing two otherwise-equivalent versions. --- ----@param v1 Version|number[] Version object. ----@param v2 Version|number[] Version to compare with `v1`. +---@param v1 Version|number[]|string Version object. +---@param v2 Version|number[]|string Version to compare with `v1`. ---@return integer -1 if `v1 < v2`, 0 if `v1 == v2`, 1 if `v1 > v2`. function M.cmp(v1, v2) local v1_parsed = assert(M._version(v1), create_err_msg(v1)) @@ -380,24 +381,40 @@ function M.cmp(v1, v2) end ---Returns `true` if the given versions are equal. See |vim.version.cmp()| for usage. ----@param v1 Version|number[] ----@param v2 Version|number[] +---@param v1 Version|number[]|string +---@param v2 Version|number[]|string ---@return boolean function M.eq(v1, v2) return M.cmp(v1, v2) == 0 end +---Returns `true` if `v1 <= v2`. See |vim.version.cmp()| for usage. +---@param v1 Version|number[]|string +---@param v2 Version|number[]|string +---@return boolean +function M.le(v1, v2) + return M.cmp(v1, v2) <= 0 +end + ---Returns `true` if `v1 < v2`. See |vim.version.cmp()| for usage. ----@param v1 Version|number[] ----@param v2 Version|number[] +---@param v1 Version|number[]|string +---@param v2 Version|number[]|string ---@return boolean function M.lt(v1, v2) return M.cmp(v1, v2) == -1 end +---Returns `true` if `v1 >= v2`. See |vim.version.cmp()| for usage. +---@param v1 Version|number[]|string +---@param v2 Version|number[]|string +---@return boolean +function M.ge(v1, v2) + return M.cmp(v1, v2) >= 0 +end + ---Returns `true` if `v1 > v2`. See |vim.version.cmp()| for usage. ----@param v1 Version|number[] ----@param v2 Version|number[] +---@param v1 Version|number[]|string +---@param v2 Version|number[]|string ---@return boolean function M.gt(v1, v2) return M.cmp(v1, v2) == 1 @@ -417,7 +434,7 @@ end --- - strict (boolean): Default false. If `true`, no coercion is attempted on --- input not conforming to semver v2.0.0. If `false`, `parse()` attempts to --- coerce input such as "1.0", "0-x", "tmux 3.2a" into valid versions. ----@return table|nil parsed_version Version object or `nil` if input is invalid. +---@return Version? parsed_version Version object or `nil` if input is invalid. function M.parse(version, opts) assert(type(version) == 'string', create_err_msg(version)) opts = opts or { strict = false } @@ -426,6 +443,7 @@ end setmetatable(M, { --- Returns the current Nvim version. + ---@return Version __call = function() local version = vim.fn.api_info().version -- Workaround: vim.fn.api_info().version reports "prerelease" as a boolean. -- cgit From d66ed4ea468d411668713c3777ad3658f18badf3 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 22 Jan 2024 08:49:45 +0100 Subject: refactor(api): give "hl_group" more accurate _meta type These can either be number or string in lua, so we can specify this directly as "number|string". --- runtime/lua/vim/_meta/api_keysets.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index 377060256a..5ebedc977b 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -246,7 +246,7 @@ error('Cannot require a meta file') --- @field end_line? integer --- @field end_row? integer --- @field end_col? integer ---- @field hl_group? integer +--- @field hl_group? number|string --- @field virt_text? any[] --- @field virt_text_pos? string --- @field virt_text_win_col? integer @@ -264,10 +264,10 @@ error('Cannot require a meta file') --- @field virt_lines_leftcol? boolean --- @field strict? boolean --- @field sign_text? string ---- @field sign_hl_group? integer ---- @field number_hl_group? integer ---- @field line_hl_group? integer ---- @field cursorline_hl_group? integer +--- @field sign_hl_group? number|string +--- @field number_hl_group? number|string +--- @field line_hl_group? number|string +--- @field cursorline_hl_group? number|string --- @field conceal? string --- @field spell? boolean --- @field ui_watched? boolean -- cgit From 12d123959f56636473112d86ec5977ef993c58e5 Mon Sep 17 00:00:00 2001 From: Raphael Date: Mon, 22 Jan 2024 16:04:50 +0800 Subject: fix(eval): properly support checking v:lua function in exists() (#27124) --- runtime/lua/vim/_meta/vimfn.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 50f6e4da52..011bfb7c11 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -1709,6 +1709,7 @@ function vim.fn.exepath(expr) end --- echo exists("*strftime") --- echo exists("*s:MyFunc") --- echo exists("*MyFunc") +--- echo exists("*v:lua.Func") --- echo exists("bufcount") --- echo exists(":Make") --- echo exists("#CursorHold") -- cgit From 1233ac467de7504b277425988ef9be7f8d3a9626 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 22 Jan 2024 10:13:35 +0000 Subject: feat(fold): transparent foldtext 'foldtext' can be set to an empty string to disable and render the line with: - extmark highlight - syntax highlighting - search highlighting - no line wrapping - spelling - conceal - inline virtual text - respects `fillchars:fold` Currently normal virtual text is not displayed Co-authored-by: zeertzjq --- runtime/lua/vim/_meta/options.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index c9e2e302dc..60339f57d8 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -2473,6 +2473,9 @@ vim.go.fdo = vim.go.foldopen --- It is not allowed to change text or jump to another window while --- evaluating 'foldtext' `textlock`. --- +--- When set to an empty string, foldtext is disabled, and the line +--- is displayed normally with highlighting and no line wrapping. +--- --- @type string vim.o.foldtext = "foldtext()" vim.o.fdt = vim.o.foldtext -- cgit From cb6320e13f9a4f13ec745ce0bc34203cfa7612d0 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Jan 2024 22:54:45 +0800 Subject: docs(options): remove misleading sentence (#27129) Setting 'verbose' to 1 doesn't cause Nvim to produce messages. It adds more information to existing messages, which is documented above. --- runtime/lua/vim/_meta/options.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 60339f57d8..1a215b1715 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -7432,15 +7432,15 @@ vim.bo.vts = vim.bo.vartabstop --- Sets the verbosity level. Also set by `-V` and `:verbose`. --- ---- Tracing of options in Lua scripts is activated at level 1; Lua scripts ---- are not traced with verbose=0, for performance. +--- Tracing of assignments to options, mappings, etc. in Lua scripts is +--- enabled at level 1; Lua scripts are not traced when 'verbose' is 0, +--- for performance. --- --- If greater than or equal to a given level, Nvim produces the following --- messages: --- --- Level Messages ~ --- ---------------------------------------------------------------------- ---- 1 Lua assignments to options, mappings, etc. --- 2 When a file is ":source"'ed, or `shada` file is read or written. --- 3 UI info, terminal capabilities. --- 4 Shell commands. -- cgit From eb5d15e3838f53e2fcd25989c88db87458e9f984 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 7 Jan 2024 13:05:03 +0100 Subject: refactor: rewrite python provider in lua --- runtime/lua/vim/provider/python.lua | 150 ++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 runtime/lua/vim/provider/python.lua (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/provider/python.lua b/runtime/lua/vim/provider/python.lua new file mode 100644 index 0000000000..94872437db --- /dev/null +++ b/runtime/lua/vim/provider/python.lua @@ -0,0 +1,150 @@ +local M = {} +local min_version = '3.7' +local s_err ---@type string? +local s_host ---@type string? + +local python_candidates = { + 'python3', + 'python3.12', + 'python3.11', + 'python3.10', + 'python3.9', + 'python3.8', + 'python3.7', + 'python', +} + +--- @param prog string +--- @param module string +--- @return integer, string +local function import_module(prog, module) + local program = [[ +import sys, importlib.util; +sys.path = [p for p in sys.path if p != ""]; +sys.stdout.write(str(sys.version_info[0]) + "." + str(sys.version_info[1]));]] + + program = program + .. string.format('sys.exit(2 * int(importlib.util.find_spec("%s") is None))', module) + + local out = vim.system({ prog, '-W', 'ignore', '-c', program }):wait() + return out.code, assert(out.stdout) +end + +--- @param prog string +--- @param module string +--- @return string? +local function check_for_module(prog, module) + local prog_path = vim.fn.exepath(prog) + if prog_path == '' then + return prog .. ' not found in search path or not executable.' + end + + -- Try to load module, and output Python version. + -- Exit codes: + -- 0 module can be loaded. + -- 2 module cannot be loaded. + -- Otherwise something else went wrong (e.g. 1 or 127). + local prog_exitcode, prog_version = import_module(prog, module) + if prog_exitcode == 2 or prog_exitcode == 0 then + -- Check version only for expected return codes. + if vim.version.lt(prog_version, min_version) then + return string.format( + '%s is Python %s and cannot provide Python >= %s.', + prog_path, + prog_version, + min_version + ) + end + end + + if prog_exitcode == 2 then + return string.format('%s does not have the "%s" module.', prog_path, module) + elseif prog_exitcode == 127 then + -- This can happen with pyenv's shims. + return string.format('%s does not exist: %s', prog_path, prog_version) + elseif prog_exitcode ~= 0 then + return string.format( + 'Checking %s caused an unknown error. (%s, output: %s) Report this at https://github.com/neovim/neovim', + prog_path, + prog_exitcode, + prog_version + ) + end + + return nil +end + +--- @param module string +--- @return string? path to detected python, if any; nil if not found +--- @return string? error message if python can't be detected by {module}; nil if success +function M.detect_by_module(module) + local python_exe = vim.fn.expand(vim.g.python3_host_prog or '', true) + + if python_exe ~= '' then + return vim.fn.exepath(vim.fn.expand(python_exe, true)), nil + end + + local errors = {} + for _, exe in ipairs(python_candidates) do + local error = check_for_module(exe, module) + if not error then + return exe, error + end + -- Accumulate errors in case we don't find any suitable Python executable. + table.insert(errors, error) + end + + -- No suitable Python executable found. + return nil, 'Could not load Python :\n' .. table.concat(errors, '\n') +end + +function M.require(host) + -- Python host arguments + local prog = M.detect_by_module('neovim') + local args = { + prog, + '-c', + 'import sys; sys.path = [p for p in sys.path if p != ""]; import neovim; neovim.start_host()', + } + + -- Collect registered Python plugins into args + local python_plugins = vim.fn['remote#host#PluginsForHost'](host.name) ---@type any + ---@param plugin any + for _, plugin in ipairs(python_plugins) do + table.insert(args, plugin.path) + end + + return vim.fn['provider#Poll']( + args, + host.orig_name, + '$NVIM_PYTHON_LOG_FILE', + { ['overlapped'] = true } + ) +end + +function M.call(method, args) + if s_err then + return + end + + if not s_host then + -- Ensure that we can load the Python3 host before bootstrapping + local ok, result = pcall(vim.fn['remote#host#Require'], 'legacy-python3-provider') ---@type any, any + if not ok then + s_err = result + vim.api.nvim_echo({ result, 'WarningMsg' }, true, {}) + return + end + s_host = result + end + + return vim.fn.rpcrequest(s_host, 'python_' .. method, unpack(args)) +end + +function M.start() + -- The Python3 provider plugin will run in a separate instance of the Python3 host. + vim.fn['remote#host#RegisterClone']('legacy-python3-provider', 'python3') + vim.fn['remote#host#RegisterPlugin']('legacy-python3-provider', 'script_host.py', {}) +end + +return M -- cgit From 89ffdebd20fd1d9c1ceff5fb005db11a0cf8c4d4 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Tue, 23 Jan 2024 01:04:20 -0500 Subject: fix(diagnostic): fix typing on field |diagnostic-severity| Problem: vim.diagnostic.{underline,float,virtual_text...}.severity will have a type warning on list-like or table (min-max) inputs, e.g. `vim.diagnostic.config { float = { severity = { min = INFO } } }`. Solution: Correct the typing as documented in |diagnostic-severity|. --- runtime/lua/vim/diagnostic.lua | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 03a1fe9a2f..8845fb5b61 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -38,7 +38,7 @@ local M = {} --- @field scope? 'line'|'buffer'|'cursor'|'c'|'l'|'b' --- @field pos? integer|{[1]:integer,[2]:integer} --- @field severity_sort? boolean|{reverse?:boolean} ---- @field severity? vim.diagnostic.Severity +--- @field severity? vim.diagnostic.SeverityFilter --- @field header? string|{[1]:string,[2]:any} --- @field source? boolean|string --- @field format? fun(diagnostic:vim.Diagnostic): string @@ -47,10 +47,10 @@ local M = {} --- @field focus_id? string --- @class vim.diagnostic.Opts.Underline ---- @field severity? vim.diagnostic.Severity +--- @field severity? vim.diagnostic.SeverityFilter --- @class vim.diagnostic.Opts.VirtualText ---- @field severity? vim.diagnostic.Severity +--- @field severity? vim.diagnostic.SeverityFilter --- @field source? boolean|string --- @field prefix? string|function --- @field suffix? string|function @@ -63,7 +63,7 @@ local M = {} --- @field virt_text_hide? boolean --- @class vim.diagnostic.Opts.Signs ---- @field severity? vim.diagnostic.Severity +--- @field severity? vim.diagnostic.SeverityFilter --- @field priority? integer --- @field text? table --- @field numhl? table @@ -84,6 +84,9 @@ M.severity = { --- @alias vim.diagnostic.SeverityInt 1|2|3|4 +--- See |diagnostic-severity| and |vim.diagnostic.get()| +--- @alias vim.diagnostic.SeverityFilter vim.diagnostic.Severity|vim.diagnostic.Severity[]|{min:vim.diagnostic.Severity,max:vim.diagnostic.Severity} + -- Mappings from qflist/loclist error types to severities M.severity.E = M.severity.ERROR M.severity.W = M.severity.WARN @@ -186,7 +189,7 @@ local function to_severity(severity) return severity end ---- @param severity vim.diagnostic.Severity|vim.diagnostic.Severity[]|{min:vim.diagnostic.Severity,max:vim.diagnostic.Severity} +--- @param severity vim.diagnostic.SeverityFilter --- @param diagnostics vim.Diagnostic[] --- @return vim.Diagnostic[] local function filter_by_severity(severity, diagnostics) @@ -1016,7 +1019,7 @@ end --- @class vim.diagnostic.GetOpts --- @field namespace? integer --- @field lnum? integer ---- @field severity? vim.diagnostic.Severity +--- @field severity? vim.diagnostic.SeverityFilter --- @class vim.diagnostic.GotoOpts : vim.diagnostic.GetOpts --- @field cursor_position? {[1]:integer,[2]:integer} @@ -1258,7 +1261,7 @@ M.handlers.virtual_text = { return end - local severity --- @type vim.diagnostic.Severity? + local severity --- @type vim.diagnostic.SeverityFilter? if opts.virtual_text then if opts.virtual_text.format then diagnostics = reformat_diagnostics(opts.virtual_text.format, diagnostics) -- cgit From 0054c185001e54316c0ee36841dfe111878a321d Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 23 Jan 2024 00:53:15 +0000 Subject: test: typing for screen.lua Very rough buts resolves most diagnostic errors and should provide some useful hovers. --- runtime/lua/vim/_editor.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index fd49f63558..c130eb1958 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -352,7 +352,7 @@ function vim.schedule_wrap(fn) end -- vim.fn.{func}(...) ----@private +---@nodoc vim.fn = setmetatable({}, { __index = function(t, key) local _fn -- cgit From 617d1b28d6d3241199a9ea4f7e68b650549d3251 Mon Sep 17 00:00:00 2001 From: Phạm Huy Hoàng Date: Tue, 23 Jan 2024 18:06:54 +0900 Subject: fix(treesitter): prefix treesitter types with vim --- runtime/lua/vim/treesitter.lua | 8 ++++---- runtime/lua/vim/treesitter/highlighter.lua | 28 ++++++++++++++-------------- runtime/lua/vim/treesitter/language.lua | 6 +++--- runtime/lua/vim/treesitter/query.lua | 2 +- 4 files changed, 22 insertions(+), 22 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 7b795380fe..3c91be7acf 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -5,10 +5,10 @@ local Range = require('vim.treesitter._range') ---@type table local parsers = setmetatable({}, { __mode = 'v' }) ----@class TreesitterModule ----@field highlighter TSHighlighter ----@field query TSQueryModule ----@field language TSLanguageModule +---@class vim.treesitter +---@field highlighter vim.treesitter.highlighter +---@field query vim.treesitter.query +---@field language vim.treesitter.language local M = setmetatable({}, { __index = function(t, k) ---@diagnostic disable:no-unknown diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 5ffdd79326..84d40322fe 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -4,9 +4,9 @@ local Range = require('vim.treesitter._range') local ns = api.nvim_create_namespace('treesitter/highlighter') ----@alias vim.TSHlIter fun(end_line: integer|nil): integer, TSNode, TSMetadata +---@alias vim.treesitter.highlighter.Iter fun(end_line: integer|nil): integer, TSNode, TSMetadata ----@class vim.TSHighlighterQuery +---@class vim.treesitter.highlighter.Query ---@field private _query Query? ---@field private lang string ---@field private hl_cache table @@ -16,7 +16,7 @@ TSHighlighterQuery.__index = TSHighlighterQuery ---@private ---@param lang string ---@param query_string string? ----@return vim.TSHighlighterQuery +---@return vim.treesitter.highlighter.Query function TSHighlighterQuery.new(lang, query_string) local self = setmetatable({}, TSHighlighterQuery) self.lang = lang @@ -52,20 +52,20 @@ function TSHighlighterQuery:query() return self._query end ----@class vim.TSHighlightState +---@class vim.treesitter.highlighter.State ---@field tstree TSTree ---@field next_row integer ----@field iter vim.TSHlIter? ----@field highlighter_query vim.TSHighlighterQuery +---@field iter vim.treesitter.highlighter.Iter? +---@field highlighter_query vim.treesitter.highlighter.Query ----@class vim.TSHighlighter ----@field active table +---@class vim.treesitter.highlighter +---@field active table ---@field bufnr integer ---@field orig_spelloptions string --- A map of highlight states. --- This state is kept during rendering across each line update. ----@field _highlight_states vim.TSHighlightState[] ----@field _queries table +---@field _highlight_states vim.treesitter.highlighter.State[] +---@field _queries table ---@field tree LanguageTree ---@field redraw_count integer local TSHighlighter = { @@ -81,7 +81,7 @@ TSHighlighter.__index = TSHighlighter ---@param tree LanguageTree parser object to use for highlighting ---@param opts (table|nil) Configuration of the highlighter: --- - queries table overwrite queries used by the highlighter ----@return vim.TSHighlighter Created highlighter object +---@return vim.treesitter.highlighter Created highlighter object function TSHighlighter.new(tree, opts) local self = setmetatable({}, TSHighlighter) @@ -202,7 +202,7 @@ function TSHighlighter:prepare_highlight_states(srow, erow) end) end ----@param fn fun(state: vim.TSHighlightState) +---@param fn fun(state: vim.treesitter.highlighter.State) ---@package function TSHighlighter:for_each_highlight_state(fn) for _, state in ipairs(self._highlight_states) do @@ -234,7 +234,7 @@ end -- ---@package ---@param lang string Language used by the highlighter. ----@return vim.TSHighlighterQuery +---@return vim.treesitter.highlighter.Query function TSHighlighter:get_query(lang) if not self._queries[lang] then self._queries[lang] = TSHighlighterQuery.new(lang) @@ -243,7 +243,7 @@ function TSHighlighter:get_query(lang) return self._queries[lang] end ----@param self vim.TSHighlighter +---@param self vim.treesitter.highlighter ---@param buf integer ---@param line integer ---@param is_spell_nav boolean diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 2105a1d992..06d6e266f1 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -1,6 +1,6 @@ local api = vim.api ----@class TSLanguageModule +---@class vim.treesitter.language local M = {} ---@type table @@ -57,7 +57,7 @@ function M.require_language(lang, path, silent, symbol_name) return true end ----@class treesitter.RequireLangOpts +---@class vim.treesitter.language.RequireLangOpts ---@field path? string ---@field silent? boolean ---@field filetype? string|string[] @@ -74,7 +74,7 @@ end --- - path (string|nil) Optional path the parser is located at --- - symbol_name (string|nil) Internal symbol name for the language to load function M.add(lang, opts) - ---@cast opts treesitter.RequireLangOpts + ---@cast opts vim.treesitter.language.RequireLangOpts opts = opts or {} local path = opts.path local filetype = opts.filetype or lang diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index cc8fe319e8..23e5ff1e6b 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -12,7 +12,7 @@ Query.__index = Query ---@field captures table ---@field patterns table ----@class TSQueryModule +---@class vim.treesitter.query local M = {} ---@param files string[] -- cgit From 8c044f0862f417a525eaf319471c286a5588d493 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 24 Jan 2024 18:13:39 +0800 Subject: fix(spell): always accept ':' as filename char in 'spellfile' (#27172) Follow-up to #25236 --- runtime/lua/vim/_meta/options.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 1a215b1715..83da61cc2b 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -6135,7 +6135,7 @@ vim.bo.spc = vim.bo.spellcapcheck --- Name of the word list file where words are added for the `zg` and `zw` --- commands. It must end in ".{encoding}.add". You need to include the --- path, otherwise the file is placed in the current directory. ---- The path may include characters from 'isfname', space, comma and '@'. +--- The path may include characters from 'isfname', ' ', ',', '@' and ':'. --- *E765* --- It may also be a comma-separated list of names. A count before the --- `zg` and `zw` commands can be used to access each. This allows using -- cgit From 576db141be6e4d9b5d9b840c599bac670df25d1a Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 22 Jan 2024 22:07:14 +0100 Subject: refactor: rewrite perl provider in lua --- runtime/lua/vim/provider/perl.lua | 66 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 runtime/lua/vim/provider/perl.lua (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/provider/perl.lua b/runtime/lua/vim/provider/perl.lua new file mode 100644 index 0000000000..8918c9792e --- /dev/null +++ b/runtime/lua/vim/provider/perl.lua @@ -0,0 +1,66 @@ +local M = {} +local s_err ---@type string? +local s_host ---@type string? + +function M.require(host, prog) + local args = { prog, '-e', 'use Neovim::Ext; start_host();' } + + -- Collect registered perl plugins into args + local perl_plugins = vim.fn['remote#host#PluginsForHost'](host.name) ---@type any + ---@param plugin any + for _, plugin in ipairs(perl_plugins) do + table.insert(args, plugin.path) + end + + return vim.fn['provider#Poll'](args, host.orig_name, '$NVIM_PERL_LOG_FILE') +end + +--- @return string? path to detected perl, if any; nil if not found +--- @return string? error message if perl can't be detected; nil if success +function M.detect() + -- use g:perl_host_prog if set or check if perl is on the path + local prog = vim.fn.exepath(vim.g.perl_host_prog or 'perl') + if prog == '' then + return nil, 'No perl executable found' + end + + -- if perl is available, make sure we have 5.22+ + vim.fn.system({ prog, '-e', 'use v5.22' }) + if vim.v.shell_error ~= 0 then + return nil, 'Perl version is too old, 5.22+ required' + end + + -- if perl is available, make sure the required module is available + vim.fn.system({ prog, '-W', '-MNeovim::Ext', '-e', '' }) + if vim.v.shell_error ~= 0 then + return nil, '"Neovim::Ext" cpan module is not installed' + end + return prog, nil +end + +function M.call(method, args) + if s_err then + return + end + + if not s_host then + -- Ensure that we can load the Perl host before bootstrapping + local ok, result = pcall(vim.fn['remote#host#Require'], 'legacy-perl-provider') ---@type any, any + if not ok then + s_err = result + vim.api.nvim_echo({ result, 'WarningMsg' }, true, {}) + return + end + s_host = result + end + + return vim.fn.rpcrequest(s_host, 'perl_' .. method, unpack(args)) +end + +function M.start() + -- The perl provider plugin will run in a separate instance of the perl host. + vim.fn['remote#host#RegisterClone']('legacy-perl-provider', 'perl') + vim.fn['remote#host#RegisterPlugin']('legacy-perl-provider', 'ScriptHost.pm', {}) +end + +return M -- cgit From 32849d56671cc74d7a1b0858638c698444ac237f Mon Sep 17 00:00:00 2001 From: Daniel Kongsgaard Date: Sun, 21 Jan 2024 17:46:14 +0100 Subject: fix(treesitter): avoid # of nil in _query_linter --- runtime/lua/vim/treesitter/_query_linter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua index 87d74789a3..8651e187c2 100644 --- a/runtime/lua/vim/treesitter/_query_linter.lua +++ b/runtime/lua/vim/treesitter/_query_linter.lua @@ -92,7 +92,7 @@ local function get_error_entry(err, node) end_col = end_col + #underlined elseif msg:match('^Invalid') then -- Use the length of the problematic type/capture/field - end_col = end_col + #msg:match('"([^"]+)"') + end_col = end_col + #(msg:match('"([^"]+)"') or '') end return { -- cgit From b280d57db9845359186bfb5167e1559b6184f8d5 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 22 Jan 2024 22:07:14 +0100 Subject: refactor: rewrite ruby provider in lua --- runtime/lua/vim/provider/perl.lua | 2 +- runtime/lua/vim/provider/python.lua | 2 +- runtime/lua/vim/provider/ruby.lua | 61 +++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 runtime/lua/vim/provider/ruby.lua (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/provider/perl.lua b/runtime/lua/vim/provider/perl.lua index 8918c9792e..da4af0a2a7 100644 --- a/runtime/lua/vim/provider/perl.lua +++ b/runtime/lua/vim/provider/perl.lua @@ -48,7 +48,7 @@ function M.call(method, args) local ok, result = pcall(vim.fn['remote#host#Require'], 'legacy-perl-provider') ---@type any, any if not ok then s_err = result - vim.api.nvim_echo({ result, 'WarningMsg' }, true, {}) + vim.api.nvim_echo({ { result, 'WarningMsg' } }, true, {}) return end s_host = result diff --git a/runtime/lua/vim/provider/python.lua b/runtime/lua/vim/provider/python.lua index 94872437db..8322131238 100644 --- a/runtime/lua/vim/provider/python.lua +++ b/runtime/lua/vim/provider/python.lua @@ -132,7 +132,7 @@ function M.call(method, args) local ok, result = pcall(vim.fn['remote#host#Require'], 'legacy-python3-provider') ---@type any, any if not ok then s_err = result - vim.api.nvim_echo({ result, 'WarningMsg' }, true, {}) + vim.api.nvim_echo({ { result, 'WarningMsg' } }, true, {}) return end s_host = result diff --git a/runtime/lua/vim/provider/ruby.lua b/runtime/lua/vim/provider/ruby.lua new file mode 100644 index 0000000000..3ad86001f3 --- /dev/null +++ b/runtime/lua/vim/provider/ruby.lua @@ -0,0 +1,61 @@ +local M = {} +local s_err ---@type string? +local s_host ---@type string? + +function M.require(host) + local prog = M.detect() + local args = { prog } + local ruby_plugins = vim.fn['remote#host#PluginsForHost'](host.name) ---@type any + + ---@param plugin any + for _, plugin in ipairs(ruby_plugins) do + table.insert(args, plugin.path) + end + + return vim.fn['provider#Poll'](args, host.orig_name, '$NVIM_RUBY_LOG_FILE') +end + +function M.call(method, args) + if s_err then + return + end + + if not s_host then + local ok, result = pcall(vim.fn['remote#host#Require'], 'legacy-ruby-provider') ---@type any, any + if not ok then + s_err = result + vim.api.nvim_echo({ { result, 'WarningMsg' } }, true, {}) + return + end + s_host = result + end + + return vim.fn.rpcrequest(s_host, 'ruby_' .. method, unpack(args)) +end + +function M.detect() + local prog ---@type string + if vim.g.ruby_host_prog then + prog = vim.fn.expand(vim.g.ruby_host_prog, true) + elseif vim.fn.has('win32') == 1 then + prog = vim.fn.exepath('neovim-ruby-host.bat') + else + local p = vim.fn.exepath('neovim-ruby-host') + if p == '' then + prog = '' + else + -- neovim-ruby-host could be an rbenv shim for another Ruby version. + vim.fn.system(p) + prog = vim.v.shell_error ~= 0 and '' or p + end + end + local err = prog == '' and 'missing ruby or ruby-host' or '' + return prog, err +end + +function M.start(plugin_path) + vim.fn['remote#host#RegisterClone']('legacy-ruby-provider', 'ruby') + vim.fn['remote#host#RegisterPlugin']('legacy-ruby-provider', plugin_path, {}) +end + +return M -- cgit From 6ea6b3fee27d51607ca4a5ace46dbc38a4481bcb Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Wed, 24 Jan 2024 16:36:25 -0600 Subject: feat(ui): add support for OSC 8 hyperlinks (#27109) Extmarks can contain URLs which can then be drawn in any supporting UI. In the TUI, for example, URLs are "drawn" by emitting the OSC 8 control sequence to the TTY. On terminals which support the OSC 8 sequence this will create clickable hyperlinks. URLs are treated as inline highlights in the decoration subsystem, so are included in the `DecorSignHighlight` structure. However, unlike other inline highlights they use allocated memory which must be freed, so they set the `ext` flag in `DecorInline` so that their lifetimes are managed along with other allocated memory like virtual text. The decoration subsystem then adds the URLs as a new highlight attribute. The highlight subsystem maintains a set of unique URLs to avoid duplicating allocations for the same string. To attach a URL to an existing highlight attribute we call `hl_add_url` which finds the URL in the set (allocating and adding it if it does not exist) and sets the `url` highlight attribute to the index of the URL in the set (using an index helps keep the size of the `HlAttrs` struct small). This has the potential to lead to an increase in highlight attributes if a URL is used over a range that contains many different highlight attributes, because now each existing attribute must be combined with the URL. In practice, however, URLs typically span a range containing a single highlight (e.g. link text in Markdown), so this is likely just a pathological edge case. When a new highlight attribute is defined with a URL it is copied to all attached UIs with the `hl_attr_define` UI event. The TUI manages its own set of URLs (just like the highlight subsystem) to minimize allocations. The TUI keeps track of which URL is "active" for the cell it is printing. If no URL is active and a cell containing a URL is printed, the opening OSC 8 sequence is emitted and that URL becomes the actively tracked URL. If the cursor is moved while in the middle of a URL span, we emit the terminating OSC sequence to prevent the hyperlink from spanning multiple lines. This does not support nested hyperlinks, but that is a rare (and, frankly, bizarre) use case. If a valid use case for nested hyperlinks ever presents itself we can address that issue then. --- runtime/lua/vim/_meta/api.lua | 3 +++ runtime/lua/vim/_meta/api_keysets.lua | 2 ++ 2 files changed, 5 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index f773ddd75c..076aae7dbe 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -607,6 +607,9 @@ function vim.api.nvim_buf_line_count(buffer) end --- drawn by a UI. When set, the UI will receive win_extmark --- events. Note: the mark is positioned by virt_text --- attributes. Can be used together with virt_text. +--- • url: A URL to associate with this extmark. In the TUI, the +--- OSC 8 control sequence is used to generate a clickable +--- hyperlink to this URL. --- @return integer function vim.api.nvim_buf_set_extmark(buffer, ns_id, line, col, opts) end diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index 5ebedc977b..00d3ff5bb4 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -192,6 +192,7 @@ error('Cannot require a meta file') --- @field fg_indexed? boolean --- @field bg_indexed? boolean --- @field force? boolean +--- @field url? string --- @class vim.api.keyset.highlight_cterm --- @field bold? boolean @@ -272,6 +273,7 @@ error('Cannot require a meta file') --- @field spell? boolean --- @field ui_watched? boolean --- @field undo_restore? boolean +--- @field url? string --- @class vim.api.keyset.user_command --- @field addr? any -- cgit From 76a659eb773ca69d8b6a8f08e1a5c538dc03b8fd Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Thu, 25 Jan 2024 00:34:18 +0100 Subject: docs: various fixes (#27063) Co-authored-by: lmenou Co-authored-by: altermo <107814000+altermo@users.noreply.github.com> Co-authored-by: VanaIgr Co-authored-by: Gregory Anders --- runtime/lua/vim/_meta/vimfn.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 011bfb7c11..7f5860c3a3 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -9684,7 +9684,7 @@ function vim.fn.synIDtrans(synID) end --- --- @param lnum integer --- @param col integer ---- @return {[1]: integer, [2]: string, [3]: integer}[] +--- @return {[1]: integer, [2]: string, [3]: integer} function vim.fn.synconcealed(lnum, col) end --- Return a |List|, which is the stack of syntax items at the -- cgit From 226466a46941cd6b693f56b6eb7f4293d4066c8d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 26 Jan 2024 11:04:54 +0800 Subject: vim-patch:9.1.0058: Cannot map Super Keys in GTK UI (#27204) Problem: Cannot map Super Keys in GTK UI (Casey Tucker) Solution: Enable Super Key mappings in GTK using (Casey Tucker) As a developer who works in both Mac and Linux using the same keyboard, it can be frustrating having to remember different key combinations or having to rely on system utilities to remap keys. This change allows `` `` `` `` etc. to be recognized by the `map` commands, along with the `` shifted variants. ```vimrc if has('gui_gtk') nnoremap u nnoremap vnoremap "+d vnoremap "+y cnoremap + inoremap "+gP nnoremap "+P vnoremap "-d"+P nnoremap :w inoremap :w nnoremap :q nnoremap :qa nnoremap :tabe nnoremap :vs#T nnoremap ggVG vnoremap ggVG inoremap ggVG nnoremap / nnoremap n nnoremap N vnoremap "+x endif ``` closes: vim/vim#12698 https://github.com/vim/vim/commit/92e90a1e102825aa9149262cacfc991264db05df Co-authored-by: Casey Tucker --- runtime/lua/vim/_meta/vimfn.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 7f5860c3a3..2280eec5c8 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -2777,7 +2777,7 @@ function vim.fn.getchar() end --- 32 mouse double click --- 64 mouse triple click --- 96 mouse quadruple click (== 32 + 64) ---- 128 command (Macintosh only) +--- 128 command (Mac) or super --- Only the modifiers that have not been included in the --- character itself are obtained. Thus Shift-a results in "A" --- without a modifier. Returns 0 if no modifiers are used. -- cgit From 28d1640dd6043f25cd3ae761dc9c4c8d374a8ce1 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 26 Jan 2024 11:38:19 +0000 Subject: feat: improve return type annotations for vim.api.* --- runtime/lua/vim/_meta/api.lua | 28 ++--- runtime/lua/vim/_meta/api_keysets_extra.lua | 167 ++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+), 14 deletions(-) create mode 100644 runtime/lua/vim/_meta/api_keysets_extra.lua (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 076aae7dbe..f9fa364158 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -320,7 +320,7 @@ function vim.api.nvim_buf_get_commands(buffer, opts) end --- • details: Whether to include the details dict --- • hl_name: Whether to include highlight group name instead --- of id, true if omitted ---- @return integer[] +--- @return vim.api.keyset.get_extmark_item function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end --- Gets `extmarks` in "traversal order" from a `charwise` region defined by @@ -376,14 +376,14 @@ function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end --- if their start position is less than `start` --- • type: Filter marks by type: "highlight", "sign", --- "virt_text" and "virt_lines" ---- @return any[] +--- @return vim.api.keyset.get_extmark_item[] function vim.api.nvim_buf_get_extmarks(buffer, ns_id, start, end_, opts) end --- Gets a list of buffer-local `mapping` definitions. --- --- @param buffer integer Buffer handle, or 0 for current buffer --- @param mode string Mode short-name ("n", "i", "v", ...) ---- @return table[] +--- @return vim.api.keyset.keymap[] function vim.api.nvim_buf_get_keymap(buffer, mode) end --- Gets a line-range from the buffer. @@ -1153,7 +1153,7 @@ function vim.api.nvim_get_all_options_info() end --- • buffer: Buffer number or list of buffer numbers for buffer --- local autocommands `autocmd-buflocal`. Cannot be used with --- {pattern} ---- @return any[] +--- @return vim.api.keyset.get_autocmds.ret[] function vim.api.nvim_get_autocmds(opts) end --- Gets information about a channel. @@ -1179,7 +1179,7 @@ function vim.api.nvim_get_color_by_name(name) end --- Keys are color names (e.g. "Aqua") and values are 24-bit RGB color values --- (e.g. 65535). --- ---- @return table +--- @return table function vim.api.nvim_get_color_map() end --- Gets a map of global (non-buffer-local) Ex commands. @@ -1229,7 +1229,7 @@ function vim.api.nvim_get_current_win() end --- instead of effective definition `:hi-link`. --- • create: (boolean, default true) When highlight group --- doesn't exist create it. ---- @return table +--- @return vim.api.keyset.hl_info function vim.api.nvim_get_hl(ns_id, opts) end --- @deprecated @@ -1264,7 +1264,7 @@ function vim.api.nvim_get_hl_ns(opts) end --- Gets a list of global (non-buffer-local) `mapping` definitions. --- --- @param mode string Mode short-name ("n", "i", "v", ...) ---- @return table[] +--- @return vim.api.keyset.keymap[] function vim.api.nvim_get_keymap(mode) end --- Returns a `(row, col, buffer, buffername)` tuple representing the position @@ -1274,18 +1274,18 @@ function vim.api.nvim_get_keymap(mode) end --- --- @param name string Mark name --- @param opts vim.api.keyset.empty Optional parameters. Reserved for future use. ---- @return any[] +--- @return vim.api.keyset.get_mark function vim.api.nvim_get_mark(name, opts) end --- Gets the current mode. `mode()` "blocking" is true if Nvim is waiting for --- input. --- ---- @return table +--- @return vim.api.keyset.get_mode function vim.api.nvim_get_mode() end --- Gets existing, non-anonymous `namespace`s. --- ---- @return table +--- @return table function vim.api.nvim_get_namespaces() end --- @deprecated @@ -1295,7 +1295,7 @@ function vim.api.nvim_get_option(name) end --- @deprecated --- @param name string ---- @return table +--- @return vim.api.keyset.get_option_info function vim.api.nvim_get_option_info(name) end --- Gets the option information for one option from arbitrary buffer or window @@ -1325,7 +1325,7 @@ function vim.api.nvim_get_option_info(name) end --- • win: `window-ID`. Used for getting window local options. --- • buf: Buffer number. Used for getting buffer local options. --- Implies {scope} is "local". ---- @return table +--- @return vim.api.keyset.get_option_info function vim.api.nvim_get_option_info2(name, opts) end --- Gets the value of an option. The behavior of this function matches that of @@ -1637,7 +1637,7 @@ function vim.api.nvim_out_write(str) end --- --- @param str string Command line string to parse. Cannot contain "\n". --- @param opts vim.api.keyset.empty Optional parameters. Reserved for future use. ---- @return table +--- @return vim.api.keyset.parse_cmd function vim.api.nvim_parse_cmd(str, opts) end --- Parse a Vimscript expression. @@ -1985,7 +1985,7 @@ function vim.api.nvim_win_get_buf(window) end --- `relative` is empty for normal windows. --- --- @param window integer Window handle, or 0 for current window ---- @return table +--- @return vim.api.keyset.float_config function vim.api.nvim_win_get_config(window) end --- Gets the (1,0)-indexed, buffer-relative cursor position for a given window diff --git a/runtime/lua/vim/_meta/api_keysets_extra.lua b/runtime/lua/vim/_meta/api_keysets_extra.lua new file mode 100644 index 0000000000..8e34ee534c --- /dev/null +++ b/runtime/lua/vim/_meta/api_keysets_extra.lua @@ -0,0 +1,167 @@ +--- @meta _ +error('Cannot require a meta file') + +--- Extra types we can't generate keysets for + +--- @class vim.api.keyset.extmark_details +--- @field ns_id integer +--- @field right_gravity boolean +--- +--- @field end_row? integer +--- @field end_col? integer +--- @field end_right_gravity? integer +--- +--- @field priority? integer +--- +--- @field undo_restore? false +--- @field invalidate? true +--- @field invalid? true +--- +--- @field hl_group? string +--- @field hl_eol? boolean +--- +--- @field conceal? boolean +--- @field spell? boolean +--- @field ui_watched? boolean +--- @field url? boolean +--- @field hl_mode? string +--- +--- @field virt_text? {[1]: string, [2]: string}[] +--- @field virt_text_hide? boolean +--- @field virt_text_repeat_linebreak? boolean +--- @field virt_text_win_col? integer +--- @field virt_text_pos? string +--- +--- @field virt_lines? {[1]: string, [2]: string}[][] +--- @field virt_lines_above? boolean +--- @field virt_lines_leftcol? boolean +--- +--- @field sign_text? string +--- @field sign_name? string +--- @field sign_hl_group? string +--- @field number_hl_group? string +--- @field line_hl_group? string +--- @field cursorline_hl_group? string + +--- @class vim.api.keyset.get_extmark_item +--- @field [1] integer row +--- @field [2] integer col +--- @field [3] vim.api.keyset.extmark_details? + +--- @class vim.api.keyset.get_mark +--- @field [1] integer row +--- @field [2] integer col +--- @field [3] integer buffer +--- @field [4] string buffername + +--- @class vim.api.keyset.get_autocmds.ret +--- @field id? integer +--- @field group? integer +--- @field group_name? integer +--- @field desc? string +--- @field event? string +--- @field command? string +--- @field callback? function +--- @field once? boolean +--- @field pattern? string +--- @field buflocal? boolean +--- @field buffer? integer + +--- @class vim.api.keyset.command_info +--- @field name string +--- @field definition string +--- @field script_id integer +--- @field bang boolean +--- @field bar boolean +--- @field register boolean +--- @field keepscript boolean +--- @field preview boolean +--- @field nargs string +--- @field complete? string +--- @field complete_arg? string +--- @field count? string +--- @field range? string +--- @field addr? string + +--- @class vim.api.keyset.hl_info.base +--- @field reverse? true +--- @field bold? true +--- @field italic? true +--- @field underline? true +--- @field undercurl? true +--- @field underdouble? true +--- @field underdotted? true +--- @field underdashed? true +--- @field standout? true +--- @field strikethrough? true +--- @field altfont? true +--- @field nocombine? true + +--- @class vim.api.keyset.hl_info.cterm : vim.api.keyset.hl_info.base +--- @field ctermfg? integer +--- @field ctermbg? integer +--- @field foreground? integer +--- @field background? integer + +--- @class vim.api.keyset.hl_info : vim.api.keyset.hl_info.base +--- @field fg? integer +--- @field bg? integer +--- @field sp? integer +--- @field default? true +--- @field link? string +--- @field blend? integer +--- @field cterm? vim.api.keyset.hl_info.cterm + +--- @class vim.api.keyset.get_mode +--- @field blocking boolean +--- @field mode string + +--- @class vim.api.keyset.get_option_info +--- @field name string +--- @field shortname string +--- @field scope 'buf'|'win'|'global' +--- @field global_local boolean +--- @field commalist boolean +--- @field flaglist boolean +--- @field was_set boolean +--- @field last_set_id integer +--- @field last_set_linenr integer +--- @field last_set_chan integer +--- @field type 'string'|'boolean'|'number' +--- @field default string|boolean|integer +--- @field allow_duplicates boolean + +--- @class vim.api.keyset.parse_cmd.mods +--- @field filter { force: boolean, pattern: string } +--- @field silent boolean +--- @field emsg_silent boolean +--- @field unsilent boolean +--- @field sandbox boolean +--- @field noautocmd boolean +--- @field tab integer +--- @field verbose integer +--- @field browse boolean +--- @field confirm boolean +--- @field hide boolean +--- @field keepalt boolean +--- @field keepjumps boolean +--- @field keepmarks boolean +--- @field keeppatterns boolean +--- @field lockmarks boolean +--- @field noswapfile boolean +--- @field vertical boolean +--- @field horizontal boolean +--- @field split ''|'botright'|'topleft'|'belowright'|'aboveleft' + +--- @class vim.api.keyset.parse_cmd +--- @field addr 'line'|'arg'|'buf'|'load'|'win'|'tab'|'qf'|'none'|'?' +--- @field args string[] +--- @field bang boolean +--- @field cmd string +--- @field magic {bar: boolean, file: boolean} +--- @field mods vim.api.keyset.parse_cmd.mods +--- @field nargs '0'|'1'|'?'|'+'|'*' +--- @field nextcmd string +--- @field range? integer[] +--- @field count? integer +--- @field reg? string -- cgit From 0892c080d16776366a2fe289f9083cdc532ec56c Mon Sep 17 00:00:00 2001 From: Till Bungert Date: Sat, 27 Jan 2024 01:38:56 +0100 Subject: revert: "feat(treesitter): add foldtext with treesitter highlighting" This reverts commit 9ce1623 in favor of #20750. --- runtime/lua/vim/treesitter.lua | 12 ----- runtime/lua/vim/treesitter/_fold.lua | 93 ------------------------------------ 2 files changed, 105 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 3c91be7acf..9d96ab33fa 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -517,16 +517,4 @@ function M.foldexpr(lnum) return require('vim.treesitter._fold').foldexpr(lnum) end ---- Returns the highlighted content of the first line of the fold or falls back to |foldtext()| ---- if no treesitter parser is found. Can be set directly to 'foldtext': ---- ---- ```lua ---- vim.wo.foldtext = 'v:lua.vim.treesitter.foldtext()' ---- ``` ---- ----@return { [1]: string, [2]: string[] }[] | string -function M.foldtext() - return require('vim.treesitter._fold').foldtext() -end - return M diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua index 735627d29f..d96cc966de 100644 --- a/runtime/lua/vim/treesitter/_fold.lua +++ b/runtime/lua/vim/treesitter/_fold.lua @@ -397,97 +397,4 @@ api.nvim_create_autocmd('OptionSet', { end end, }) - ----@package ----@return { [1]: string, [2]: string[] }[]|string -function M.foldtext() - local foldstart = vim.v.foldstart - local bufnr = api.nvim_get_current_buf() - - ---@type boolean, LanguageTree - local ok, parser = pcall(ts.get_parser, bufnr) - if not ok then - return vim.fn.foldtext() - end - - local query = ts.query.get(parser:lang(), 'highlights') - if not query then - return vim.fn.foldtext() - end - - local tree = parser:parse({ foldstart - 1, foldstart })[1] - - local line = api.nvim_buf_get_lines(bufnr, foldstart - 1, foldstart, false)[1] - if not line then - return vim.fn.foldtext() - end - - ---@type { [1]: string, [2]: string[], range: { [1]: integer, [2]: integer } }[] | { [1]: string, [2]: string[] }[] - local result = {} - - local line_pos = 0 - - for id, node, metadata in query:iter_captures(tree:root(), 0, foldstart - 1, foldstart) do - local name = query.captures[id] - local start_row, start_col, end_row, end_col = node:range() - - local priority = tonumber(metadata.priority or vim.highlight.priorities.treesitter) - - if start_row == foldstart - 1 and end_row == foldstart - 1 then - -- check for characters ignored by treesitter - if start_col > line_pos then - table.insert(result, { - line:sub(line_pos + 1, start_col), - {}, - range = { line_pos, start_col }, - }) - end - line_pos = end_col - - local text = line:sub(start_col + 1, end_col) - table.insert(result, { text, { { '@' .. name, priority } }, range = { start_col, end_col } }) - end - end - - local i = 1 - while i <= #result do - -- find first capture that is not in current range and apply highlights on the way - local j = i + 1 - while - j <= #result - and result[j].range[1] >= result[i].range[1] - and result[j].range[2] <= result[i].range[2] - do - for k, v in ipairs(result[i][2]) do - if not vim.tbl_contains(result[j][2], v) then - table.insert(result[j][2], k, v) - end - end - j = j + 1 - end - - -- remove the parent capture if it is split into children - if j > i + 1 then - table.remove(result, i) - else - -- highlights need to be sorted by priority, on equal prio, the deeper nested capture (earlier - -- in list) should be considered higher prio - if #result[i][2] > 1 then - table.sort(result[i][2], function(a, b) - return a[2] < b[2] - end) - end - - result[i][2] = vim.tbl_map(function(tbl) - return tbl[1] - end, result[i][2]) - result[i] = { result[i][1], result[i][2] } - - i = i + 1 - end - end - - return result -end - return M -- cgit From d85f180f26c0570c2510c899a0bf0023ec55a692 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Tue, 15 Aug 2023 19:38:52 +0100 Subject: vim-patch:9.1.0049: Make "[Command Line]" a special buffer name Problem: E95 is possible if a buffer called "[Command Line]" already exists when opening the cmdwin. This can also happen if the cmdwin's buffer could not be deleted when closing. Solution: Un-name the cmdwin buffer, and give it a special name instead, similar to what's done for quickfix buffers and for unnamed prompt and scratch buffers. As a result, BufFilePre/Post are no longer fired when opening the cmdwin. Add a "command" key to the dictionary returned by getbufinfo() to differentiate the cmdwin buffer instead. (Sean Dewar) Cherry-pick test_normal changes from v9.0.0954. https://github.com/vim/vim/commit/1fb41032060df09ca2640dc49541f11062f6dfaa --- runtime/lua/vim/_meta/vimfn.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 2280eec5c8..acf3750500 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -2562,6 +2562,8 @@ function vim.fn.getbufinfo(buf) end --- bufnr Buffer number. --- changed TRUE if the buffer is modified. --- changedtick Number of changes made to the buffer. +--- command TRUE if the buffer belongs to the +--- command-line window |cmdwin|. --- hidden TRUE if the buffer is hidden. --- lastused Timestamp in seconds, like --- |localtime()|, when the buffer was -- cgit From 5b1b765610ae12ebd6400aafd068903569ee441a Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Sun, 28 Jan 2024 20:53:14 -0500 Subject: docs: enforce "treesitter" spelling #27110 It's the "tree-sitter" project, but "treesitter" in our code and docs. --- runtime/lua/vim/filetype.lua | 2 +- runtime/lua/vim/highlight.lua | 2 +- runtime/lua/vim/treesitter/dev.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 7e1803f640..fbcca2dcfd 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1909,7 +1909,7 @@ local pattern = { ['.*baseq[2-3]/.*%.cfg'] = 'quake', ['.*quake[1-3]/.*%.cfg'] = 'quake', ['.*id1/.*%.cfg'] = 'quake', - ['.*/queries/.*%.scm'] = 'query', -- tree-sitter queries (Neovim only) + ['.*/queries/.*%.scm'] = 'query', -- treesitter queries (Neovim only) ['.*,v'] = 'rcs', ['%.reminders.*'] = starsetf('remind'), ['[rR]akefile.*'] = starsetf('ruby'), diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua index fc2fd43c97..1d04f95d2d 100644 --- a/runtime/lua/vim/highlight.lua +++ b/runtime/lua/vim/highlight.lua @@ -26,7 +26,7 @@ local M = {} --- Table with default priorities used for highlighting: --- - `syntax`: `50`, used for standard syntax highlighting ---- - `treesitter`: `100`, used for tree-sitter-based highlighting +--- - `treesitter`: `100`, used for treesitter-based highlighting --- - `semantic_tokens`: `125`, used for LSP semantic token highlighting --- - `diagnostics`: `150`, used for code analysis such as diagnostics --- - `user`: `200`, used for user-triggered highlights such as LSP document diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 399d0ef03e..5020dd87e7 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -14,7 +14,7 @@ local M = {} local TSTreeView = {} ---@class TSP.Node ----@field node TSNode Tree-sitter node +---@field node TSNode Treesitter node ---@field field string? Node field ---@field depth integer Depth of this node in the tree ---@field text string? Text displayed in the inspector for this node. Not computed until the -- cgit From eee52d3427e2c97c0e9a9347bafdd55d49830ec7 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Sun, 28 Jan 2024 18:38:36 -0800 Subject: refactor(lsp): client_hints typo #27250 --- runtime/lua/vim/lsp/inlay_hint.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua index 4816b873ba..62138c0edf 100644 --- a/runtime/lua/vim/lsp/inlay_hint.lua +++ b/runtime/lua/vim/lsp/inlay_hint.lua @@ -6,7 +6,7 @@ local M = {} ---@class lsp.inlay_hint.bufstate ---@field version? integer ----@field client_hint? table> client_id -> (lnum -> hints) +---@field client_hints? table> client_id -> (lnum -> hints) ---@field applied table Last version of hints applied to this line ---@field enabled boolean Whether inlay hints are enabled for this buffer ---@type table @@ -39,11 +39,11 @@ function M.on_inlayhint(err, result, ctx, _) if not bufstate or not bufstate.enabled then return end - if not (bufstate.client_hint and bufstate.version) then - bufstate.client_hint = vim.defaulttable() + if not (bufstate.client_hints and bufstate.version) then + bufstate.client_hints = vim.defaulttable() bufstate.version = ctx.version end - local hints_by_client = bufstate.client_hint + local hints_by_client = bufstate.client_hints local client = assert(vim.lsp.get_client_by_id(client_id)) local new_hints_by_lnum = vim.defaulttable() @@ -162,7 +162,7 @@ function M.get(filter) end local bufstate = bufstates[bufnr] - if not (bufstate and bufstate.client_hint) then + if not (bufstate and bufstate.client_hints) then return {} end @@ -185,7 +185,7 @@ function M.get(filter) --- @type vim.lsp.inlay_hint.get.ret[] local hints = {} for _, client in pairs(clients) do - local hints_by_lnum = bufstate.client_hint[client.id] + local hints_by_lnum = bufstate.client_hints[client.id] if hints_by_lnum then for lnum = range.start.line, range['end'].line do local line_hints = hints_by_lnum[lnum] or {} @@ -218,11 +218,11 @@ local function clear(bufnr) return end local bufstate = bufstates[bufnr] - local client_lens = (bufstate or {}).client_hint or {} + local client_lens = (bufstate or {}).client_hints or {} local client_ids = vim.tbl_keys(client_lens) --- @type integer[] for _, iter_client_id in ipairs(client_ids) do if bufstate then - bufstate.client_hint[iter_client_id] = {} + bufstate.client_hints[iter_client_id] = {} end end api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1) @@ -319,7 +319,7 @@ api.nvim_set_decoration_provider(namespace, { if bufstate.version ~= util.buf_versions[bufnr] then return end - local hints_by_client = assert(bufstate.client_hint) + local hints_by_client = assert(bufstate.client_hints) for lnum = topline, botline do if bufstate.applied[lnum] ~= bufstate.version then -- cgit From 15e77a56b711102fdc123e15b3f37d49bc0b1df1 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Sun, 28 Jan 2024 21:13:58 -0600 Subject: feat(extmarks): subpriorities (relative to declaration order) (#27131) The "priority" field of extmarks can be used to set priorities of extmarks which dictates which highlight group a range will actually have when there are multiple extmarks applied. However, when multiple extmarks have the same priority, the only way to enforce an actual priority is through the order in which the extmarks are set. It is not always possible or desirable to set extmarks in a specific order, however, so we add a new "subpriority" field that explicitly enforces the ordering of extmarks that have the same priority. For now this will be used only to enforce priority of treesitter highlights. A single node in a treesitter tree may match multiple captures, in which case that node will have multiple extmarks set. The order in which captures are returned from the treesitter API is not _necessarily_ in the same order they are defined in a query file, so we use the new subpriority field to force that ordering. For now subpriorites are not documented and are not meant to be used by external code, and it only applies to ephemeral extmarks. We indicate the "private" nature of subpriorities by prefixing the field name with an "_". --- runtime/lua/vim/_meta/api_keysets.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index 00d3ff5bb4..c9ef4e9b4f 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -274,6 +274,7 @@ error('Cannot require a meta file') --- @field ui_watched? boolean --- @field undo_restore? boolean --- @field url? string +--- @field _subpriority? integer --- @class vim.api.keyset.user_command --- @field addr? any -- cgit From ca9f6f56949d66f0f6467fa64b215f861fe0a3bf Mon Sep 17 00:00:00 2001 From: Will Hopkins Date: Sun, 28 Jan 2024 23:18:33 -0800 Subject: feat(api): add nvim_tabpage_set_win (#27222) Allows setting the current window of a non-current tabpage without switching tabpages. --- runtime/lua/vim/_meta/api.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index f9fa364158..bedc218626 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1952,6 +1952,12 @@ function vim.api.nvim_tabpage_list_wins(tabpage) end --- @param value any Variable value function vim.api.nvim_tabpage_set_var(tabpage, name, value) end +--- Sets the current window in a tabpage +--- +--- @param tabpage integer Tabpage handle, or 0 for current tabpage +--- @param win integer Window handle, must already belong to {tabpage} +function vim.api.nvim_tabpage_set_win(tabpage, win) end + --- Calls a function with window as temporary current window. --- --- @param window integer Window handle, or 0 for current window -- cgit From 6bba4becedaea5a330c0c9d9427fb495e8092dac Mon Sep 17 00:00:00 2001 From: Will Hopkins Date: Wed, 31 Jan 2024 19:43:35 -0800 Subject: feat(api): make nvim_open_win support non-floating windows (#25550) Adds support to `nvim_open_win` and `nvim_win_set_config` for creating and manipulating split (non-floating) windows. --- runtime/lua/vim/_meta/api.lua | 39 +++++++++++++++++++++++++++-------- runtime/lua/vim/_meta/api_keysets.lua | 2 ++ 2 files changed, 32 insertions(+), 9 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index bedc218626..77a29cb4c1 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1483,15 +1483,24 @@ function vim.api.nvim_notify(msg, log_level, opts) end --- @return integer function vim.api.nvim_open_term(buffer, opts) end ---- Open a new window. ---- Currently this is used to open floating and external windows. Floats are ---- windows that are drawn above the split layout, at some anchor position in ---- some other window. Floats can be drawn internally or by external GUI with ---- the `ui-multigrid` extension. External windows are only supported with ---- multigrid GUIs, and are displayed as separate top-level windows. +--- Opens a new split window, or a floating window if `relative` is specified, +--- or an external window (managed by the UI) if `external` is specified. +--- Floats are windows that are drawn above the split layout, at some anchor +--- position in some other window. Floats can be drawn internally or by +--- external GUI with the `ui-multigrid` extension. External windows are only +--- supported with multigrid GUIs, and are displayed as separate top-level +--- windows. --- For a general overview of floats, see `api-floatwin`. ---- Exactly one of `external` and `relative` must be specified. The `width` ---- and `height` of the new window must be specified. +--- The `width` and `height` of the new window must be specified when opening +--- a floating window, but are optional for normal windows. +--- If `relative` and `external` are omitted, a normal "split" window is +--- created. The `win` property determines which window will be split. If no +--- `win` is provided or `win == 0`, a window will be created adjacent to the +--- current window. If -1 is provided, a top-level split will be created. +--- `vertical` and `split` are only valid for normal windows, and are used to +--- control split direction. For `vertical`, the exact direction is determined +--- by `'splitright'` and `'splitbelow'`. Split windows cannot have +--- `bufpos`/`row`/`col`/`border`/`title`/`footer` properties. --- With relative=editor (row=0,col=0) refers to the top-left corner of the --- screen-grid and (row=Lines-1,col=Columns-1) refers to the bottom-right --- corner. Fractional values are allowed, but the builtin implementation @@ -1515,6 +1524,15 @@ function vim.api.nvim_open_term(buffer, opts) end --- {relative='win', width=12, height=3, bufpos={100,10}}) --- ``` --- +--- Example (Lua): vertical split left of the current window +--- +--- ```lua +--- vim.api.nvim_open_win(0, false, { +--- split = 'left', +--- win = 0 +--- }) +--- ``` +--- --- @param buffer integer Buffer to display, or 0 for current buffer --- @param enter boolean Enter the window (make it the current window) --- @param config vim.api.keyset.float_config Map defining the window configuration. Keys: @@ -1526,7 +1544,8 @@ function vim.api.nvim_open_term(buffer, opts) end --- • "cursor" Cursor position in current window. --- • "mouse" Mouse position --- ---- • win: `window-ID` for relative="win". +--- • win: `window-ID` window to split, or relative window when +--- creating a float (relative="win"). --- • anchor: Decides which corner of the float to place at --- (row,col): --- • "NW" northwest (default) @@ -1623,6 +1642,8 @@ function vim.api.nvim_open_term(buffer, opts) end --- • fixed: If true when anchor is NW or SW, the float window --- would be kept fixed even if the window would be truncated. --- • hide: If true the floating window will be hidden. +--- • vertical: Split vertically `:vertical`. +--- • split: Split direction: "left", "right", "above", "below". --- @return integer function vim.api.nvim_open_win(buffer, enter, config) end diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index c9ef4e9b4f..1b6c6811a2 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -118,10 +118,12 @@ error('Cannot require a meta file') --- @field height? integer --- @field anchor? string --- @field relative? string +--- @field split? string --- @field win? integer --- @field bufpos? any[] --- @field external? boolean --- @field focusable? boolean +--- @field vertical? boolean --- @field zindex? integer --- @field border? any --- @field title? any -- cgit From 9b7cf4f0beb35b640846f92ac522372967ca6695 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 2 Feb 2024 21:52:01 +0800 Subject: fix(vim.system): don't process non-fast events during wait() (#27300) Problem: Processing non-fast events during SystemObj:wait() may cause two pieces of code to interfere with each other, and is different from jobwait(). Solution: Don't process non-fast events during SystemObj:wait(). --- runtime/lua/vim/_system.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_system.lua b/runtime/lua/vim/_system.lua index efad3f88cf..e97a5fc6c3 100644 --- a/runtime/lua/vim/_system.lua +++ b/runtime/lua/vim/_system.lua @@ -94,14 +94,14 @@ function SystemObj:wait(timeout) local done = vim.wait(timeout or state.timeout or MAX_TIMEOUT, function() return state.result ~= nil - end) + end, nil, true) if not done then -- Send sigkill since this cannot be caught self:_timeout(SIG.KILL) vim.wait(timeout or state.timeout or MAX_TIMEOUT, function() return state.result ~= nil - end) + end, nil, true) end return state.result -- cgit From 2e982f1aad9f1a03562b7a451d642f76b04c37cb Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 22 Jan 2024 18:23:28 +0100 Subject: refactor: create function for deferred loading The benefit of this is that users only pay for what they use. If e.g. only `vim.lsp.buf_get_clients()` is called then they don't need to load all modules under `vim.lsp` which could lead to significant startuptime saving. Also `vim.lsp.module` is a bit nicer to user compared to `require("vim.lsp.module")`. This isn't used for some nested modules such as `filetype` as it breaks tests with error messages such as "attempt to index field 'detect'". It's not entirely certain the reason for this, but it is likely it is due to filetype being precompiled which would imply deferred loading isn't needed for performance reasons. --- runtime/lua/vim/_init_packages.lua | 1 + runtime/lua/vim/diagnostic.lua | 2 +- runtime/lua/vim/lsp.lua | 71 +++++++++++++++++---------------- runtime/lua/vim/lsp/_completion.lua | 4 +- runtime/lua/vim/lsp/_dynamic.lua | 2 +- runtime/lua/vim/lsp/_watchfiles.lua | 4 +- runtime/lua/vim/lsp/diagnostic.lua | 6 +-- runtime/lua/vim/lsp/handlers.lua | 14 +++---- runtime/lua/vim/lsp/health.lua | 2 +- runtime/lua/vim/lsp/util.lua | 4 +- runtime/lua/vim/provider.lua | 7 ++++ runtime/lua/vim/shared.lua | 20 ++++++++++ runtime/lua/vim/snippet.lua | 2 +- runtime/lua/vim/treesitter.lua | 59 +++++++++------------------ runtime/lua/vim/treesitter/health.lua | 2 +- runtime/lua/vim/treesitter/language.lua | 1 - runtime/lua/vim/treesitter/query.lua | 9 ++--- 17 files changed, 106 insertions(+), 104 deletions(-) create mode 100644 runtime/lua/vim/provider.lua (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_init_packages.lua b/runtime/lua/vim/_init_packages.lua index 97d483333e..83ef4efb9f 100644 --- a/runtime/lua/vim/_init_packages.lua +++ b/runtime/lua/vim/_init_packages.lua @@ -60,6 +60,7 @@ vim._submodules = { iter = true, re = true, text = true, + provider = true, } -- These are for loading runtime modules in the vim namespace lazily. diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 8845fb5b61..a3a2422ab5 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -1732,7 +1732,7 @@ function M.open_float(opts, ...) if not opts.focus_id then opts.focus_id = scope end - local float_bufnr, winnr = require('vim.lsp.util').open_floating_preview(lines, 'plaintext', opts) + local float_bufnr, winnr = vim.lsp.util.open_floating_preview(lines, 'plaintext', opts) for i, hl in ipairs(highlights) do local line = lines[i] local prefix_len = hl.prefix and hl.prefix.length or 0 diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index f3448209ba..5fa5a1db29 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1,13 +1,4 @@ ---@diagnostic disable: invisible -local default_handlers = require('vim.lsp.handlers') -local log = require('vim.lsp.log') -local lsp_rpc = require('vim.lsp.rpc') -local protocol = require('vim.lsp.protocol') -local ms = protocol.Methods -local util = require('vim.lsp.util') -local changetracking = require('vim.lsp._changetracking') -local semantic_tokens = require('vim.lsp.semantic_tokens') - local api = vim.api local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_exec_autocmds = api.nvim_err_writeln, api.nvim_buf_get_lines, api.nvim_command, api.nvim_exec_autocmds @@ -16,24 +7,34 @@ local tbl_isempty, tbl_extend = vim.tbl_isempty, vim.tbl_extend local validate = vim.validate local if_nil = vim.F.if_nil -local lsp = { - protocol = protocol, - - handlers = default_handlers, - - buf = require('vim.lsp.buf'), - diagnostic = require('vim.lsp.diagnostic'), - codelens = require('vim.lsp.codelens'), - inlay_hint = require('vim.lsp.inlay_hint'), - semantic_tokens = semantic_tokens, - util = util, +local lsp = vim._defer_require('vim.lsp', { + _changetracking = ..., --- @module 'vim.lsp._changetracking' + _completion = ..., --- @module 'vim.lsp._completion' + _dynamic = ..., --- @module 'vim.lsp._dynamic' + _snippet_grammar = ..., --- @module 'vim.lsp._snippet_grammar' + _watchfiles = ..., --- @module 'vim.lsp._watchfiles' + buf = ..., --- @module 'vim.lsp.buf' + codelens = ..., --- @module 'vim.lsp.codelens' + diagnostic = ..., --- @module 'vim.lsp.diagnostic' + handlers = ..., --- @module 'vim.lsp.handlers' + inlay_hint = ..., --- @module 'vim.lsp.inlay_hint' + log = ..., --- @module 'vim.lsp.log' + protocol = ..., --- @module 'vim.lsp.protocol' + rpc = ..., --- @module 'vim.lsp.rpc' + semantic_tokens = ..., --- @module 'vim.lsp.semantic_tokens' + tagfunc = ..., --- @module 'vim.lsp.tagfunc' + util = ..., --- @module 'vim.lsp.util' +}) - -- Allow raw RPC access. - rpc = lsp_rpc, +local log = lsp.log +local protocol = lsp.protocol +local ms = protocol.Methods +local util = lsp.util +local changetracking = lsp._changetracking - -- Export these directly from rpc. - rpc_response_error = lsp_rpc.rpc_response_error, -} +-- Export these directly from rpc. +---@nodoc +lsp.rpc_response_error = lsp.rpc.rpc_response_error -- maps request name to the required server_capability in the client. lsp._request_name_to_capability = { @@ -189,11 +190,11 @@ end --- @nodoc lsp.client_errors = tbl_extend( 'error', - lsp_rpc.client_errors, + lsp.rpc.client_errors, vim.tbl_add_reverse_lookup({ - BEFORE_INIT_CALLBACK_ERROR = table.maxn(lsp_rpc.client_errors) + 1, - ON_INIT_CALLBACK_ERROR = table.maxn(lsp_rpc.client_errors) + 2, - ON_ATTACH_ERROR = table.maxn(lsp_rpc.client_errors) + 3, + BEFORE_INIT_CALLBACK_ERROR = table.maxn(lsp.rpc.client_errors) + 1, + ON_INIT_CALLBACK_ERROR = table.maxn(lsp.rpc.client_errors) + 2, + ON_ATTACH_ERROR = table.maxn(lsp.rpc.client_errors) + 3, }) ) @@ -800,7 +801,7 @@ function lsp.start_client(config) ---@param method (string) LSP method name ---@return lsp.Handler|nil handler for the given method, if defined, or the default from |vim.lsp.handlers| local function resolve_handler(method) - return handlers[method] or default_handlers[method] + return handlers[method] or lsp.handlers[method] end ---@private @@ -958,7 +959,7 @@ function lsp.start_client(config) if type(cmd) == 'function' then rpc = cmd(dispatch) else - rpc = lsp_rpc.start(cmd, cmd_args, dispatch, { + rpc = lsp.rpc.start(cmd, cmd_args, dispatch, { cwd = config.cmd_cwd, env = config.cmd_env, detached = config.detached, @@ -999,7 +1000,7 @@ function lsp.start_client(config) ---@deprecated use client.progress instead messages = { name = name, messages = {}, progress = {}, status = {} }, - dynamic_capabilities = require('vim.lsp._dynamic').new(client_id), + dynamic_capabilities = vim.lsp._dynamic.new(client_id), } ---@type table title of unfinished progress sequences by token @@ -1412,7 +1413,7 @@ function lsp.start_client(config) -- opt-out (deleting the semanticTokensProvider from capabilities) vim.schedule(function() if vim.tbl_get(client.server_capabilities, 'semanticTokensProvider', 'full') then - semantic_tokens.start(bufnr, client.id) + lsp.semantic_tokens.start(bufnr, client.id) end end) @@ -1969,7 +1970,7 @@ function lsp.omnifunc(findstart, base) if log.debug() then log.debug('omnifunc.findstart', { findstart = findstart, base = base }) end - return require('vim.lsp._completion').omnifunc(findstart, base) + return vim.lsp._completion.omnifunc(findstart, base) end --- Provides an interface between the built-in client and a `formatexpr` function. @@ -2039,7 +2040,7 @@ end --- ---@return table[] tags A list of matching tags function lsp.tagfunc(pattern, flags) - return require('vim.lsp.tagfunc')(pattern, flags) + return vim.lsp.tagfunc(pattern, flags) end ---Checks whether a client is stopped. diff --git a/runtime/lua/vim/lsp/_completion.lua b/runtime/lua/vim/lsp/_completion.lua index 7a607d6c13..84dbf9083e 100644 --- a/runtime/lua/vim/lsp/_completion.lua +++ b/runtime/lua/vim/lsp/_completion.lua @@ -8,7 +8,7 @@ local ms = protocol.Methods ---@return string parsed snippet local function parse_snippet(input) local ok, parsed = pcall(function() - return require('vim.lsp._snippet_grammar').parse(input) + return vim.lsp._snippet_grammar.parse(input) end) return ok and tostring(parsed) or input end @@ -206,7 +206,7 @@ function M.omnifunc(findstart, base) local params = util.make_position_params(win, client.offset_encoding) client.request(ms.textDocument_completion, params, function(err, result) if err then - require('vim.lsp.log').warn(err.message) + vim.lsp.log.warn(err.message) end if result and vim.fn.mode() == 'i' then local matches diff --git a/runtime/lua/vim/lsp/_dynamic.lua b/runtime/lua/vim/lsp/_dynamic.lua index 5edb27b498..3c9dee2c69 100644 --- a/runtime/lua/vim/lsp/_dynamic.lua +++ b/runtime/lua/vim/lsp/_dynamic.lua @@ -1,4 +1,4 @@ -local glob = require('vim.glob') +local glob = vim.glob --- @class lsp.DynamicCapabilities --- @field capabilities table diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua index af4cc65f71..59b8c38166 100644 --- a/runtime/lua/vim/lsp/_watchfiles.lua +++ b/runtime/lua/vim/lsp/_watchfiles.lua @@ -1,6 +1,6 @@ local bit = require('bit') -local glob = require('vim.glob') -local watch = require('vim._watch') +local glob = vim.glob +local watch = vim._watch local protocol = require('vim.lsp.protocol') local ms = protocol.Methods local lpeg = vim.lpeg diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index cba5b66672..46dda01e3f 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -1,8 +1,6 @@ ---@brief lsp-diagnostic -local util = require('vim.lsp.util') local protocol = require('vim.lsp.protocol') -local log = require('vim.lsp.log') local ms = protocol.Methods local api = vim.api @@ -95,7 +93,7 @@ local function tags_lsp_to_vim(diagnostic, client_id) tags = tags or {} tags.deprecated = true else - log.info(string.format('Unknown DiagnosticTag %d from LSP client %d', tag, client_id)) + vim.lsp.log.info(string.format('Unknown DiagnosticTag %d from LSP client %d', tag, client_id)) end end return tags @@ -425,7 +423,7 @@ end local function _refresh(bufnr, opts) opts = opts or {} opts['bufnr'] = bufnr - util._refresh(ms.textDocument_diagnostic, opts) + vim.lsp.util._refresh(ms.textDocument_diagnostic, opts) end --- Enable pull diagnostics for a buffer diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 6ed8e1d40f..26a71487e2 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -120,7 +120,7 @@ M[ms.client_registerCapability] = function(_, result, ctx) local unsupported = {} for _, reg in ipairs(result.registrations) do if reg.method == ms.workspace_didChangeWatchedFiles then - require('vim.lsp._watchfiles').register(reg, ctx) + vim.lsp._watchfiles.register(reg, ctx) elseif not client.dynamic_capabilities:supports_registration(reg.method) then unsupported[#unsupported + 1] = reg.method end @@ -144,7 +144,7 @@ M[ms.client_unregisterCapability] = function(_, result, ctx) for _, unreg in ipairs(result.unregisterations) do if unreg.method == ms.workspace_didChangeWatchedFiles then - require('vim.lsp._watchfiles').unregister(unreg, ctx) + vim.lsp._watchfiles.unregister(unreg, ctx) end end return vim.NIL @@ -223,19 +223,19 @@ M[ms.workspace_workspaceFolders] = function(_, _, ctx) end M[ms.textDocument_publishDiagnostics] = function(...) - return require('vim.lsp.diagnostic').on_publish_diagnostics(...) + return vim.lsp.diagnostic.on_publish_diagnostics(...) end M[ms.textDocument_diagnostic] = function(...) - return require('vim.lsp.diagnostic').on_diagnostic(...) + return vim.lsp.diagnostic.on_diagnostic(...) end M[ms.textDocument_codeLens] = function(...) - return require('vim.lsp.codelens').on_codelens(...) + return vim.lsp.codelens.on_codelens(...) end M[ms.textDocument_inlayHint] = function(...) - return require('vim.lsp.inlay_hint').on_inlayhint(...) + return vim.lsp.inlay_hint.on_inlayhint(...) end --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references @@ -643,7 +643,7 @@ end ---@see https://microsoft.github.io/language-server-protocol/specification/#workspace_inlayHint_refresh M[ms.workspace_inlayHint_refresh] = function(err, result, ctx, config) - return require('vim.lsp.inlay_hint').on_refresh(err, result, ctx, config) + return vim.lsp.inlay_hint.on_refresh(err, result, ctx, config) end -- Add boilerplate error validation and logging for all of these. diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua index fe06006108..9c989e5246 100644 --- a/runtime/lua/vim/lsp/health.lua +++ b/runtime/lua/vim/lsp/health.lua @@ -5,7 +5,7 @@ function M.check() local report_info = vim.health.info local report_warn = vim.health.warn - local log = require('vim.lsp.log') + local log = vim.lsp.log local current_log_level = log.get_level() local log_level_string = log.levels[current_log_level] report_info(string.format('LSP log level : %s', log_level_string)) diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index cee09d85e0..b5e15e135c 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -3,7 +3,7 @@ local snippet = require('vim.lsp._snippet_grammar') local validate = vim.validate local api = vim.api local list_extend = vim.list_extend -local highlight = require('vim.highlight') +local highlight = vim.highlight local uv = vim.uv local npcall = vim.F.npcall @@ -636,7 +636,7 @@ end ---@see complete-items function M.text_document_completion_list_to_complete_items(result, prefix) vim.deprecate('vim.lsp.util.text_document_completion_list_to_complete_items()', nil, '0.11') - return require('vim.lsp._completion')._lsp_to_complete_items(result, prefix) + return vim.lsp._completion._lsp_to_complete_items(result, prefix) end --- Like vim.fn.bufwinid except it works across tabpages. diff --git a/runtime/lua/vim/provider.lua b/runtime/lua/vim/provider.lua new file mode 100644 index 0000000000..08b3fd6cbd --- /dev/null +++ b/runtime/lua/vim/provider.lua @@ -0,0 +1,7 @@ +local M = vim._defer_require('vim.provider', { + perl = ..., --- @module 'vim.provider.perl' + python = ..., --- @module 'vim.provider.python' + ruby = ..., --- @module 'vim.provider.ruby' +}) + +return M diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index e76d148b1b..fa7690e41e 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -983,4 +983,24 @@ do end end +--- @private +--- @generic T +--- @param root string +--- @param mod T +--- @return T +function vim._defer_require(root, mod) + return setmetatable({}, { + ---@param t table + ---@param k string + __index = function(t, k) + if not mod[k] then + return + end + local name = string.format('%s.%s', root, k) + t[k] = require(name) + return t[k] + end, + }) +end + return vim diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua index ac25fb6a2d..4c62b5c076 100644 --- a/runtime/lua/vim/snippet.lua +++ b/runtime/lua/vim/snippet.lua @@ -1,4 +1,4 @@ -local G = require('vim.lsp._snippet_grammar') +local G = vim.lsp._snippet_grammar local snippet_group = vim.api.nvim_create_augroup('vim/snippet', {}) local snippet_ns = vim.api.nvim_create_namespace('vim/snippet') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 9d96ab33fa..88b68ff658 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -1,44 +1,21 @@ local api = vim.api -local LanguageTree = require('vim.treesitter.languagetree') -local Range = require('vim.treesitter._range') ---@type table local parsers = setmetatable({}, { __mode = 'v' }) ----@class vim.treesitter ----@field highlighter vim.treesitter.highlighter ----@field query vim.treesitter.query ----@field language vim.treesitter.language -local M = setmetatable({}, { - __index = function(t, k) - ---@diagnostic disable:no-unknown - if k == 'highlighter' then - t[k] = require('vim.treesitter.highlighter') - return t[k] - elseif k == 'language' then - t[k] = require('vim.treesitter.language') - return t[k] - elseif k == 'query' then - t[k] = require('vim.treesitter.query') - return t[k] - end - - local query = require('vim.treesitter.query') - if query[k] then - vim.deprecate('vim.treesitter.' .. k .. '()', 'vim.treesitter.query.' .. k .. '()', '0.10') - t[k] = query[k] - return t[k] - end - - local language = require('vim.treesitter.language') - if language[k] then - vim.deprecate('vim.treesitter.' .. k .. '()', 'vim.treesitter.language.' .. k .. '()', '0.10') - t[k] = language[k] - return t[k] - end - end, +local M = vim._defer_require('vim.treesitter', { + _fold = ..., --- @module 'vim.treesitter._fold' + _query_linter = ..., --- @module 'vim.treesitter._query_linter' + _range = ..., --- @module 'vim.treesitter._range' + dev = ..., --- @module 'vim.treesitter.dev' + highlighter = ..., --- @module 'vim.treesitter.highlighter' + language = ..., --- @module 'vim.treesitter.language' + languagetree = ..., --- @module 'vim.treesitter.languagetree' + query = ..., --- @module 'vim.treesitter.query' }) +local LanguageTree = M.languagetree + --- @nodoc M.language_version = vim._ts_get_language_version() @@ -200,7 +177,7 @@ end function M.get_range(node, source, metadata) if metadata and metadata.range then assert(source) - return Range.add_bytes(source, metadata.range) + return M._range.add_bytes(source, metadata.range) end return { node:range(true) } end @@ -209,7 +186,7 @@ end ---@param range Range ---@returns string local function buf_range_get_text(buf, range) - local start_row, start_col, end_row, end_col = Range.unpack4(range) + local start_row, start_col, end_row, end_col = M._range.unpack4(range) if end_col == 0 then if start_row == end_row then start_col = -1 @@ -237,7 +214,7 @@ function M.get_node_text(node, source, opts) if metadata.text then return metadata.text elseif type(source) == 'number' then - local range = vim.treesitter.get_range(node, source, metadata) + local range = M.get_range(node, source, metadata) return buf_range_get_text(source, range) end @@ -266,9 +243,9 @@ function M.node_contains(node, range) vim.validate({ -- allow a table so nodes can be mocked node = { node, { 'userdata', 'table' } }, - range = { range, Range.validate, 'integer list with 4 or 6 elements' }, + range = { range, M._range.validate, 'integer list with 4 or 6 elements' }, }) - return Range.contains({ node:range() }, range) + return M._range.contains({ node:range() }, range) end --- Returns a list of highlight captures at the given position @@ -502,7 +479,7 @@ end --- argument and should return a string. function M.inspect_tree(opts) ---@diagnostic disable-next-line: invisible - require('vim.treesitter.dev').inspect_tree(opts) + M.dev.inspect_tree(opts) end --- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr': @@ -514,7 +491,7 @@ end ---@param lnum integer|nil Line number to calculate fold level for ---@return string function M.foldexpr(lnum) - return require('vim.treesitter._fold').foldexpr(lnum) + return M._fold.foldexpr(lnum) end return M diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua index ed1161e97f..a9b066d158 100644 --- a/runtime/lua/vim/treesitter/health.lua +++ b/runtime/lua/vim/treesitter/health.lua @@ -1,6 +1,6 @@ local M = {} local ts = vim.treesitter -local health = require('vim.health') +local health = vim.health --- Performs a healthcheck for treesitter integration function M.check() diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 06d6e266f1..0f6d5ecbd0 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -1,6 +1,5 @@ local api = vim.api ----@class vim.treesitter.language local M = {} ---@type table diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 23e5ff1e6b..63d4a9382a 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -12,7 +12,6 @@ Query.__index = Query ---@field captures table ---@field patterns table ----@class vim.treesitter.query local M = {} ---@param files string[] @@ -799,9 +798,9 @@ end --- - clear (boolean) if `true`, just clear current lint errors function M.lint(buf, opts) if opts and opts.clear then - require('vim.treesitter._query_linter').clear(buf) + vim.treesitter._query_linter.clear(buf) else - require('vim.treesitter._query_linter').lint(buf, opts) + vim.treesitter._query_linter.lint(buf, opts) end end @@ -814,7 +813,7 @@ end --- ``` --- function M.omnifunc(findstart, base) - return require('vim.treesitter._query_linter').omnifunc(findstart, base) + return vim.treesitter._query_linter.omnifunc(findstart, base) end --- Opens a live editor to query the buffer you started from. @@ -827,7 +826,7 @@ end --- --- @param lang? string language to open the query editor for. If omitted, inferred from the current buffer's filetype. function M.edit(lang) - require('vim.treesitter.dev').edit_query(lang) + vim.treesitter.dev.edit_query(lang) end return M -- cgit From f487e5af019c7cd0f15ab9beb522c9358e8013e2 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Sat, 3 Feb 2024 17:47:56 -0500 Subject: fix(lsp): fix infinite loop on vim.lsp.tagfunc Problem: vim.lsp.tagfunc() causes an infinite loop. This is a bug happened while introducing deferred loading. Solution: Rename the private module to `vim.lsp._tagfunc`. --- runtime/lua/vim/lsp.lua | 4 +- runtime/lua/vim/lsp/_tagfunc.lua | 83 ++++++++++++++++++++++++++++++++++++++++ runtime/lua/vim/lsp/tagfunc.lua | 83 ---------------------------------------- 3 files changed, 85 insertions(+), 85 deletions(-) create mode 100644 runtime/lua/vim/lsp/_tagfunc.lua delete mode 100644 runtime/lua/vim/lsp/tagfunc.lua (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 5fa5a1db29..d8d47a8464 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -12,6 +12,7 @@ local lsp = vim._defer_require('vim.lsp', { _completion = ..., --- @module 'vim.lsp._completion' _dynamic = ..., --- @module 'vim.lsp._dynamic' _snippet_grammar = ..., --- @module 'vim.lsp._snippet_grammar' + _tagfunc = ..., --- @module 'vim.lsp._tagfunc' _watchfiles = ..., --- @module 'vim.lsp._watchfiles' buf = ..., --- @module 'vim.lsp.buf' codelens = ..., --- @module 'vim.lsp.codelens' @@ -22,7 +23,6 @@ local lsp = vim._defer_require('vim.lsp', { protocol = ..., --- @module 'vim.lsp.protocol' rpc = ..., --- @module 'vim.lsp.rpc' semantic_tokens = ..., --- @module 'vim.lsp.semantic_tokens' - tagfunc = ..., --- @module 'vim.lsp.tagfunc' util = ..., --- @module 'vim.lsp.util' }) @@ -2040,7 +2040,7 @@ end --- ---@return table[] tags A list of matching tags function lsp.tagfunc(pattern, flags) - return vim.lsp.tagfunc(pattern, flags) + return vim.lsp._tagfunc(pattern, flags) end ---Checks whether a client is stopped. diff --git a/runtime/lua/vim/lsp/_tagfunc.lua b/runtime/lua/vim/lsp/_tagfunc.lua new file mode 100644 index 0000000000..4ad50e4a58 --- /dev/null +++ b/runtime/lua/vim/lsp/_tagfunc.lua @@ -0,0 +1,83 @@ +local lsp = vim.lsp +local util = lsp.util +local ms = lsp.protocol.Methods + +---@param name string +---@param range lsp.Range +---@param uri string +---@param offset_encoding string +---@return {name: string, filename: string, cmd: string, kind?: string} +local function mk_tag_item(name, range, uri, offset_encoding) + local bufnr = vim.uri_to_bufnr(uri) + -- This is get_line_byte_from_position is 0-indexed, call cursor expects a 1-indexed position + local byte = util._get_line_byte_from_position(bufnr, range.start, offset_encoding) + 1 + return { + name = name, + filename = vim.uri_to_fname(uri), + cmd = string.format([[/\%%%dl\%%%dc/]], range.start.line + 1, byte), + } +end + +---@param pattern string +---@return table[] +local function query_definition(pattern) + local params = util.make_position_params() + local results_by_client, err = lsp.buf_request_sync(0, ms.textDocument_definition, params, 1000) + if err then + return {} + end + local results = {} + local add = function(range, uri, offset_encoding) + table.insert(results, mk_tag_item(pattern, range, uri, offset_encoding)) + end + for client_id, lsp_results in pairs(assert(results_by_client)) do + local client = lsp.get_client_by_id(client_id) + local offset_encoding = client and client.offset_encoding or 'utf-16' + local result = lsp_results.result or {} + if result.range then -- Location + add(result.range, result.uri) + else + result = result --[[@as (lsp.Location[]|lsp.LocationLink[])]] + for _, item in pairs(result) do + if item.range then -- Location + add(item.range, item.uri, offset_encoding) + else -- LocationLink + add(item.targetSelectionRange, item.targetUri, offset_encoding) + end + end + end + end + return results +end + +---@param pattern string +---@return table[] +local function query_workspace_symbols(pattern) + local results_by_client, err = + lsp.buf_request_sync(0, ms.workspace_symbol, { query = pattern }, 1000) + if err then + return {} + end + local results = {} + for client_id, responses in pairs(assert(results_by_client)) do + local client = lsp.get_client_by_id(client_id) + local offset_encoding = client and client.offset_encoding or 'utf-16' + local symbols = responses.result --[[@as lsp.SymbolInformation[]|nil]] + for _, symbol in pairs(symbols or {}) do + local loc = symbol.location + local item = mk_tag_item(symbol.name, loc.range, loc.uri, offset_encoding) + item.kind = lsp.protocol.SymbolKind[symbol.kind] or 'Unknown' + table.insert(results, item) + end + end + return results +end + +local function tagfunc(pattern, flags) + local matches = string.match(flags, 'c') and query_definition(pattern) + or query_workspace_symbols(pattern) + -- fall back to tags if no matches + return #matches > 0 and matches or vim.NIL +end + +return tagfunc diff --git a/runtime/lua/vim/lsp/tagfunc.lua b/runtime/lua/vim/lsp/tagfunc.lua deleted file mode 100644 index 4ad50e4a58..0000000000 --- a/runtime/lua/vim/lsp/tagfunc.lua +++ /dev/null @@ -1,83 +0,0 @@ -local lsp = vim.lsp -local util = lsp.util -local ms = lsp.protocol.Methods - ----@param name string ----@param range lsp.Range ----@param uri string ----@param offset_encoding string ----@return {name: string, filename: string, cmd: string, kind?: string} -local function mk_tag_item(name, range, uri, offset_encoding) - local bufnr = vim.uri_to_bufnr(uri) - -- This is get_line_byte_from_position is 0-indexed, call cursor expects a 1-indexed position - local byte = util._get_line_byte_from_position(bufnr, range.start, offset_encoding) + 1 - return { - name = name, - filename = vim.uri_to_fname(uri), - cmd = string.format([[/\%%%dl\%%%dc/]], range.start.line + 1, byte), - } -end - ----@param pattern string ----@return table[] -local function query_definition(pattern) - local params = util.make_position_params() - local results_by_client, err = lsp.buf_request_sync(0, ms.textDocument_definition, params, 1000) - if err then - return {} - end - local results = {} - local add = function(range, uri, offset_encoding) - table.insert(results, mk_tag_item(pattern, range, uri, offset_encoding)) - end - for client_id, lsp_results in pairs(assert(results_by_client)) do - local client = lsp.get_client_by_id(client_id) - local offset_encoding = client and client.offset_encoding or 'utf-16' - local result = lsp_results.result or {} - if result.range then -- Location - add(result.range, result.uri) - else - result = result --[[@as (lsp.Location[]|lsp.LocationLink[])]] - for _, item in pairs(result) do - if item.range then -- Location - add(item.range, item.uri, offset_encoding) - else -- LocationLink - add(item.targetSelectionRange, item.targetUri, offset_encoding) - end - end - end - end - return results -end - ----@param pattern string ----@return table[] -local function query_workspace_symbols(pattern) - local results_by_client, err = - lsp.buf_request_sync(0, ms.workspace_symbol, { query = pattern }, 1000) - if err then - return {} - end - local results = {} - for client_id, responses in pairs(assert(results_by_client)) do - local client = lsp.get_client_by_id(client_id) - local offset_encoding = client and client.offset_encoding or 'utf-16' - local symbols = responses.result --[[@as lsp.SymbolInformation[]|nil]] - for _, symbol in pairs(symbols or {}) do - local loc = symbol.location - local item = mk_tag_item(symbol.name, loc.range, loc.uri, offset_encoding) - item.kind = lsp.protocol.SymbolKind[symbol.kind] or 'Unknown' - table.insert(results, item) - end - end - return results -end - -local function tagfunc(pattern, flags) - local matches = string.match(flags, 'c') and query_definition(pattern) - or query_workspace_symbols(pattern) - -- fall back to tags if no matches - return #matches > 0 and matches or vim.NIL -end - -return tagfunc -- cgit From 1d5f86f6949b54445e51be67acf918bf2e15105c Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sun, 4 Feb 2024 10:57:36 +0100 Subject: vim-patch:9.1.0076: luau config file not detected Problem: luau config file not detected (lopy) Solution: Detect it as jsonc (lopy) fixes: vim/vim#13960 closes: vim/vim#13970 https://github.com/vim/vim/commit/de7f5bde6c598d4da4ce5b30328eb458962ba60a Co-authored-by: lopy <70210066+lopi-py@users.noreply.github.com> --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index fbcca2dcfd..7fa92d1664 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1341,6 +1341,7 @@ local filename = { ['.hintrc'] = 'jsonc', ['.jsfmtrc'] = 'jsonc', ['.jshintrc'] = 'jsonc', + ['.luaurc'] = 'jsonc', ['.swrc'] = 'jsonc', ['.justfile'] = 'just', Kconfig = 'kconfig', -- cgit From 6c8387067d4e3e89c29bbd2d79fffe85fec8f164 Mon Sep 17 00:00:00 2001 From: altermo <107814000+altermo@users.noreply.github.com> Date: Sun, 4 Feb 2024 12:17:21 +0100 Subject: fix(treesitter): inspect-tree remember opts on buf change --- runtime/lua/vim/treesitter/dev.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 5020dd87e7..1385642acd 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -460,7 +460,9 @@ function M.inspect_tree(opts) return true end + local treeview_opts = treeview.opts treeview = assert(TSTreeView:new(buf, opts.lang)) + treeview.opts = treeview_opts treeview:draw(b) end, }) -- cgit From 0e9a33572dc752463a0f5ad8a08a2c494d7a42e1 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Wed, 3 Jan 2024 20:05:03 -0800 Subject: fix(lsp): handle adjacent snippet tabstops --- runtime/lua/vim/snippet.lua | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua index 4c62b5c076..7e37d84393 100644 --- a/runtime/lua/vim/snippet.lua +++ b/runtime/lua/vim/snippet.lua @@ -1,6 +1,7 @@ local G = vim.lsp._snippet_grammar local snippet_group = vim.api.nvim_create_augroup('vim/snippet', {}) local snippet_ns = vim.api.nvim_create_namespace('vim/snippet') +local hl_group = 'SnippetTabstop' --- Returns the 0-based cursor position. --- @@ -117,11 +118,11 @@ local Tabstop = {} --- @return vim.snippet.Tabstop function Tabstop.new(index, bufnr, range, choices) local extmark_id = vim.api.nvim_buf_set_extmark(bufnr, snippet_ns, range[1], range[2], { - right_gravity = false, + right_gravity = true, end_right_gravity = true, end_line = range[3], end_col = range[4], - hl_group = 'SnippetTabstop', + hl_group = hl_group, }) local self = setmetatable( @@ -161,6 +162,21 @@ function Tabstop:set_text(text) vim.api.nvim_buf_set_text(self.bufnr, range[1], range[2], range[3], range[4], text_to_lines(text)) end +--- Sets the right gravity of the tabstop's extmark. +--- +--- @package +--- @param right_gravity boolean +function Tabstop:set_right_gravity(right_gravity) + local range = self:get_range() + self.extmark_id = vim.api.nvim_buf_set_extmark(self.bufnr, snippet_ns, range[1], range[2], { + right_gravity = right_gravity, + end_right_gravity = true, + end_line = range[3], + end_col = range[4], + hl_group = hl_group, + }) +end + --- @class vim.snippet.Session --- @field bufnr integer --- @field extmark_id integer @@ -218,6 +234,17 @@ function Session:get_dest_index(direction) end end +--- Sets the right gravity of the tabstop group with the given index. +--- +--- @package +--- @param index integer +--- @param right_gravity boolean +function Session:set_group_gravity(index, right_gravity) + for _, tabstop in ipairs(self.tabstops[index]) do + tabstop:set_right_gravity(right_gravity) + end +end + --- @class vim.snippet.Snippet --- @field private _session? vim.snippet.Session local M = { session = nil } @@ -560,9 +587,15 @@ function M.jump(direction) -- Clear the autocommands so that we can move the cursor freely while selecting the tabstop. vim.api.nvim_clear_autocmds({ group = snippet_group, buffer = M._session.bufnr }) + -- Deactivate expansion of the current tabstop. + M._session:set_group_gravity(M._session.current_tabstop.index, true) + M._session.current_tabstop = dest select_tabstop(dest) + -- Activate expansion of the destination tabstop. + M._session:set_group_gravity(dest.index, false) + -- Restore the autocommands. setup_autocmds(M._session.bufnr) end -- cgit From a478bf936b2a648312704c02898eb7e5bfbf5692 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Thu, 1 Feb 2024 15:34:35 -0500 Subject: feat(treesitter): use 0-based indexing to show ranges in `:InspectTree` Problem: - `:InspectTree` was showing node ranges in 1-based indexing, i.e., in vim cursor position (lnum, col). However, treesitter API adopts 0-based indexing to represent ranges (Range4). This can often be confusing for developers and plugin authors when debugging code written with treesiter APIs. Solution: - Change to 0-based indexing from 1-based indexing to show node ranges in `:InspectTree`. - Note: To make things not complicated, we do not provide an option or keymap to configure which indexing mode to use. --- runtime/lua/vim/treesitter/dev.lua | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 1385642acd..e1f93a654b 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -3,16 +3,20 @@ local api = vim.api ---@class TSDevModule local M = {} +---@private ---@class TSTreeView ---@field ns integer API namespace ----@field opts table Options table with the following keys: ---- - anon (boolean): If true, display anonymous nodes ---- - lang (boolean): If true, display the language alongside each node ---- - indent (number): Number of spaces to indent nested lines. Default is 2. +---@field opts TSTreeViewOpts ---@field nodes TSP.Node[] ---@field named TSP.Node[] local TSTreeView = {} +---@private +---@class TSTreeViewOpts +---@field anon boolean If true, display anonymous nodes. +---@field lang boolean If true, display the language alongside each node. +---@field indent number Number of spaces to indent nested lines. + ---@class TSP.Node ---@field node TSNode Treesitter node ---@field field string? Node field @@ -115,6 +119,7 @@ function TSTreeView:new(bufnr, lang) ns = api.nvim_create_namespace('treesitter/dev-inspect'), nodes = nodes, named = named, + ---@type TSTreeViewOpts opts = { anon = false, lang = false, @@ -129,16 +134,12 @@ end local decor_ns = api.nvim_create_namespace('ts.dev') ----@param lnum integer ----@param col integer ----@param end_lnum integer ----@param end_col integer +---@param range Range4 ---@return string -local function get_range_str(lnum, col, end_lnum, end_col) - if lnum == end_lnum then - return string.format('[%d:%d - %d]', lnum + 1, col + 1, end_col) - end - return string.format('[%d:%d - %d:%d]', lnum + 1, col + 1, end_lnum + 1, end_col) +local function range_to_string(range) + ---@type integer, integer, integer, integer + local row, col, end_row, end_col = unpack(range) + return string.format('[%d, %d] - [%d, %d]', row, col, end_row, end_col) end ---@param w integer @@ -212,7 +213,7 @@ function TSTreeView:draw(bufnr) local lang_hl_marks = {} ---@type table[] for i, item in self:iter() do - local range_str = get_range_str(item.node:range()) + local range_str = range_to_string({ item.node:range() }) local lang_str = self.opts.lang and string.format(' %s', item.lang) or '' local text ---@type string -- cgit From 63b810c9d8543bfcbee0367554e97cb97d1c14e6 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 6 Feb 2024 12:30:02 +0100 Subject: docs: small fixes (#27213) Co-authored-by: Matthieu Coudron <886074+teto@users.noreply.github.com> --- runtime/lua/vim/diagnostic.lua | 2 +- runtime/lua/vim/uri.lua | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index a3a2422ab5..ec465f4780 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -1023,7 +1023,7 @@ end --- @class vim.diagnostic.GotoOpts : vim.diagnostic.GetOpts --- @field cursor_position? {[1]:integer,[2]:integer} ---- @field wrap? integer +--- @field wrap? boolean --- @field float? boolean|vim.diagnostic.Opts.Float --- @field win_id? integer diff --git a/runtime/lua/vim/uri.lua b/runtime/lua/vim/uri.lua index 2dc817c5c1..038aa8acfb 100644 --- a/runtime/lua/vim/uri.lua +++ b/runtime/lua/vim/uri.lua @@ -10,14 +10,14 @@ local tohex = require('bit').tohex local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):.*' local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):[a-zA-Z]:.*' local PATTERNS = { - ---RFC 2396 - ---https://tools.ietf.org/html/rfc2396#section-2.2 + -- RFC 2396 + -- https://tools.ietf.org/html/rfc2396#section-2.2 rfc2396 = "^A-Za-z0-9%-_.!~*'()", - ---RFC 2732 - ---https://tools.ietf.org/html/rfc2732 + -- RFC 2732 + -- https://tools.ietf.org/html/rfc2732 rfc2732 = "^A-Za-z0-9%-_.!~*'()[]", - ---RFC 3986 - ---https://tools.ietf.org/html/rfc3986#section-2.2 + -- RFC 3986 + -- https://tools.ietf.org/html/rfc3986#section-2.2 rfc3986 = "^A-Za-z0-9%-._~!$&'()*+,;=:@/", } -- cgit From 3be2536ca039fb0f0de4ed2858db5a6d13baeba3 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 6 Feb 2024 12:34:04 +0000 Subject: fix(lsp): send back diagnostic tags to the server Fixes: #27318 --- runtime/lua/vim/diagnostic.lua | 2 +- runtime/lua/vim/lsp/diagnostic.lua | 31 +++++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 7 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index ec465f4780..91f91b5879 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -11,7 +11,7 @@ local M = {} --- @field severity? vim.diagnostic.Severity --- @field message string --- @field source? string ---- @field code? string +--- @field code? string|integer --- @field _tags? { deprecated: boolean, unnecessary: boolean} --- @field user_data? any arbitrary data plugins can add --- @field namespace? integer diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 46dda01e3f..036b0e6151 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -102,16 +102,17 @@ end ---@param diagnostics lsp.Diagnostic[] ---@param bufnr integer ---@param client_id integer ----@return Diagnostic[] +---@return vim.Diagnostic[] local function diagnostic_lsp_to_vim(diagnostics, bufnr, client_id) local buf_lines = get_buf_lines(bufnr) local client = vim.lsp.get_client_by_id(client_id) local offset_encoding = client and client.offset_encoding or 'utf-16' - ---@diagnostic disable-next-line:no-unknown + --- @param diagnostic lsp.Diagnostic + --- @return vim.Diagnostic return vim.tbl_map(function(diagnostic) - ---@cast diagnostic lsp.Diagnostic local start = diagnostic.range.start local _end = diagnostic.range['end'] + --- @type vim.Diagnostic return { lnum = start.line, col = line_byte_from_position(buf_lines, start.line, start.character, offset_encoding), @@ -135,12 +136,29 @@ local function diagnostic_lsp_to_vim(diagnostics, bufnr, client_id) end, diagnostics) end ---- @param diagnostics Diagnostic[] +--- @param diagnostic vim.Diagnostic +--- @return lsp.DiagnosticTag[]? +local function tags_vim_to_vim(diagnostic) + if not diagnostic._tags then + return + end + + local tags = {} --- @type lsp.DiagnosticTag[] + if diagnostic._tags.unnecessary then + tags[#tags + 1] = protocol.DiagnosticTag.Unnecessary + end + if diagnostic._tags.deprecated then + tags[#tags + 1] = protocol.DiagnosticTag.Deprecated + end + return tags +end + +--- @param diagnostics vim.Diagnostic[] --- @return lsp.Diagnostic[] local function diagnostic_vim_to_lsp(diagnostics) - ---@diagnostic disable-next-line:no-unknown + ---@param diagnostic vim.Diagnostic + ---@return lsp.Diagnostic return vim.tbl_map(function(diagnostic) - ---@cast diagnostic Diagnostic return vim.tbl_extend('keep', { -- "keep" the below fields over any duplicate fields in diagnostic.user_data.lsp range = { @@ -157,6 +175,7 @@ local function diagnostic_vim_to_lsp(diagnostics) message = diagnostic.message, source = diagnostic.source, code = diagnostic.code, + tags = tags_vim_to_vim(diagnostics), }, diagnostic.user_data and (diagnostic.user_data.lsp or {}) or {}) end, diagnostics) end -- cgit From c0b99bb1de8de967d82fc29780996ed4060516c1 Mon Sep 17 00:00:00 2001 From: altermo <107814000+altermo@users.noreply.github.com> Date: Tue, 6 Feb 2024 21:51:53 +0100 Subject: feat(treesitter): show root nodes in :InspectTree (#26944) Co-authored-by: altermo <> Co-authored-by: Jongwook Choi --- runtime/lua/vim/treesitter/dev.lua | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index e1f93a654b..551067533a 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -43,25 +43,26 @@ local TSTreeView = {} --- ---@param node TSNode Starting node to begin traversal |tsnode| ---@param depth integer Current recursion depth +---@param field string|nil The field of the current node ---@param lang string Language of the tree currently being traversed ---@param injections table Mapping of node ids to root nodes --- of injected language trees (see explanation above) ---@param tree TSP.Node[] Output table containing a list of tables each representing a node in the tree -local function traverse(node, depth, lang, injections, tree) +local function traverse(node, depth, field, lang, injections, tree) + table.insert(tree, { + node = node, + depth = depth, + lang = lang, + field = field, + }) + local injection = injections[node:id()] if injection then - traverse(injection.root, depth, injection.lang, injections, tree) + traverse(injection.root, depth + 1, nil, injection.lang, injections, tree) end - for child, field in node:iter_children() do - table.insert(tree, { - node = child, - field = field, - depth = depth, - lang = lang, - }) - - traverse(child, depth + 1, lang, injections, tree) + for child, child_field in node:iter_children() do + traverse(child, depth + 1, child_field, lang, injections, tree) end return tree @@ -106,7 +107,7 @@ function TSTreeView:new(bufnr, lang) end end) - local nodes = traverse(root, 0, parser:lang(), injections, {}) + local nodes = traverse(root, 0, nil, parser:lang(), injections, {}) local named = {} ---@type TSP.Node[] for _, v in ipairs(nodes) do -- cgit From 59cf827f99d53ec8dbb90e48a7561c0cb8b8ca6f Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 7 Feb 2024 17:22:03 +0000 Subject: refactor(lsp): move client code to a regular Lua class Problem: The LSP client code is implemented as a complicated closure-class (class defined in a single function). Solution: Move LSP client code to a more conventional Lua class and move to a separate file. --- runtime/lua/vim/lsp.lua | 543 +++----------------------------- runtime/lua/vim/lsp/_dynamic.lua | 5 +- runtime/lua/vim/lsp/buf.lua | 2 +- runtime/lua/vim/lsp/client.lua | 663 +++++++++++++++++++++++++++++++++++++++ runtime/lua/vim/lsp/codelens.lua | 2 +- runtime/lua/vim/shared.lua | 1 + 6 files changed, 709 insertions(+), 507 deletions(-) create mode 100644 runtime/lua/vim/lsp/client.lua (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index d8d47a8464..dc50ab0267 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -15,6 +15,7 @@ local lsp = vim._defer_require('vim.lsp', { _tagfunc = ..., --- @module 'vim.lsp._tagfunc' _watchfiles = ..., --- @module 'vim.lsp._watchfiles' buf = ..., --- @module 'vim.lsp.buf' + client = ..., --- @module 'vim.lsp.client' codelens = ..., --- @module 'vim.lsp.codelens' diagnostic = ..., --- @module 'vim.lsp.diagnostic' handlers = ..., --- @module 'vim.lsp.handlers' @@ -259,7 +260,7 @@ end --- Validates a client configuration as given to |vim.lsp.start_client()|. --- ---@param config (lsp.ClientConfig) ----@return (string|fun(dispatchers:vim.rpc.Dispatchers):vim.lsp.rpc.PublicClient?) Command +---@return (string|fun(dispatchers:vim.lsp.rpc.Dispatchers):vim.lsp.rpc.PublicClient?) Command ---@return string[] Arguments ---@return string Encoding. local function validate_client_config(config) @@ -292,7 +293,7 @@ local function validate_client_config(config) 'flags.debounce_text_changes must be a number with the debounce time in milliseconds' ) - local cmd, cmd_args --- @type (string|fun(dispatchers:vim.rpc.Dispatchers):vim.lsp.rpc.PublicClient), string[] + local cmd, cmd_args --- @type (string|fun(dispatchers:vim.lsp.rpc.Dispatchers):vim.lsp.rpc.PublicClient), string[] local config_cmd = config.cmd if type(config_cmd) == 'function' then cmd = config_cmd @@ -341,42 +342,6 @@ local function once(fn) end end ---- Default handler for the 'textDocument/didOpen' LSP notification. ---- ----@param bufnr integer Number of the buffer, or 0 for current ----@param client lsp.Client Client object -local function text_document_did_open_handler(bufnr, client) - changetracking.init(client, bufnr) - if not vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then - return - end - if not api.nvim_buf_is_loaded(bufnr) then - return - end - local filetype = vim.bo[bufnr].filetype - - local params = { - textDocument = { - version = 0, - uri = vim.uri_from_bufnr(bufnr), - languageId = client.config.get_language_id(bufnr, filetype), - text = lsp._buf_get_full_text(bufnr), - }, - } - client.notify(ms.textDocument_didOpen, params) - util.buf_versions[bufnr] = params.textDocument.version - - -- Next chance we get, we should re-do the diagnostics - vim.schedule(function() - -- Protect against a race where the buffer disappears - -- between `did_open_handler` and the scheduled function firing. - if api.nvim_buf_is_valid(bufnr) then - local namespace = vim.lsp.diagnostic.get_namespace(client.id) - vim.diagnostic.show(namespace, bufnr) - end - end) -end - -- FIXME: DOC: Shouldn't need to use a dummy function -- --- LSP client object. You can get an active client object via @@ -556,7 +521,9 @@ function lsp.status() local percentage = nil local messages = {} --- @type string[] for _, client in ipairs(vim.lsp.get_clients()) do + --- @diagnostic disable-next-line:no-unknown for progress in client.progress do + --- @cast progress {token: lsp.ProgressToken, value: lsp.LSPAny} local value = progress.value if type(value) == 'table' and value.kind then local message = value.message and (value.title .. ': ' .. value.message) or value.title @@ -655,6 +622,26 @@ end --- @field flags table --- @field root_dir string +--- Reset defaults set by `set_defaults`. +--- Must only be called if the last client attached to a buffer exits. +local function reset_defaults(bufnr) + if vim.bo[bufnr].tagfunc == 'v:lua.vim.lsp.tagfunc' then + vim.bo[bufnr].tagfunc = nil + end + if vim.bo[bufnr].omnifunc == 'v:lua.vim.lsp.omnifunc' then + vim.bo[bufnr].omnifunc = nil + end + if vim.bo[bufnr].formatexpr == 'v:lua.vim.lsp.formatexpr()' then + vim.bo[bufnr].formatexpr = nil + end + api.nvim_buf_call(bufnr, function() + local keymap = vim.fn.maparg('K', 'n', false, true) + if keymap and keymap.callback == vim.lsp.buf.hover then + vim.keymap.del('n', 'K', { buffer = bufnr }) + end + end) +end + -- FIXME: DOC: Currently all methods on the `vim.lsp.client` object are -- documented twice: Here, and on the methods themselves (e.g. -- `client.request()`). This is a workaround for the vimdoc generator script @@ -875,26 +862,6 @@ function lsp.start_client(config) end end - --- Reset defaults set by `set_defaults`. - --- Must only be called if the last client attached to a buffer exits. - local function reset_defaults(bufnr) - if vim.bo[bufnr].tagfunc == 'v:lua.vim.lsp.tagfunc' then - vim.bo[bufnr].tagfunc = nil - end - if vim.bo[bufnr].omnifunc == 'v:lua.vim.lsp.omnifunc' then - vim.bo[bufnr].omnifunc = nil - end - if vim.bo[bufnr].formatexpr == 'v:lua.vim.lsp.formatexpr()' then - vim.bo[bufnr].formatexpr = nil - end - api.nvim_buf_call(bufnr, function() - local keymap = vim.fn.maparg('K', 'n', false, true) - if keymap and keymap.callback == vim.lsp.buf.hover then - vim.keymap.del('n', 'K', { buffer = bufnr }) - end - end) - end - ---@private --- Invoked on client exit. --- @@ -971,456 +938,26 @@ function lsp.start_client(config) return end - ---@class lsp.Client - local client = { - id = client_id, - name = name, - rpc = rpc, - offset_encoding = offset_encoding, - config = config, - attached_buffers = {}, --- @type table - - handlers = handlers, - --- @type table - commands = config.commands or {}, + config.capabilities = config.capabilities or protocol.make_client_capabilities() - --- @type table - requests = {}, - - --- Contains $/progress report messages. - --- They have the format {token: integer|string, value: any} - --- For "work done progress", value will be one of: - --- - lsp.WorkDoneProgressBegin, - --- - lsp.WorkDoneProgressReport (extended with title from Begin) - --- - lsp.WorkDoneProgressEnd (extended with title from Begin) - progress = vim.ringbuf(50), - - --- @type lsp.ServerCapabilities - server_capabilities = {}, - - ---@deprecated use client.progress instead - messages = { name = name, messages = {}, progress = {}, status = {} }, - dynamic_capabilities = vim.lsp._dynamic.new(client_id), - } - - ---@type table title of unfinished progress sequences by token - client.progress.pending = {} - - --- @type lsp.ClientCapabilities - client.config.capabilities = config.capabilities or protocol.make_client_capabilities() + local client = require('vim.lsp.client').new(client_id, rpc, handlers, offset_encoding, config) -- Store the uninitialized_clients for cleanup in case we exit before initialize finishes. uninitialized_clients[client_id] = client - local function initialize() - local valid_traces = { - off = 'off', - messages = 'messages', - verbose = 'verbose', - } - - local workspace_folders --- @type lsp.WorkspaceFolder[]? - local root_uri --- @type string? - local root_path --- @type string? - if config.workspace_folders or config.root_dir then - if config.root_dir and not config.workspace_folders then - workspace_folders = { - { - uri = vim.uri_from_fname(config.root_dir), - name = string.format('%s', config.root_dir), - }, - } - else - workspace_folders = config.workspace_folders - end - root_uri = workspace_folders[1].uri - root_path = vim.uri_to_fname(root_uri) - else - workspace_folders = nil - root_uri = nil - root_path = nil - end - - local initialize_params = { - -- The process Id of the parent process that started the server. Is null if - -- the process has not been started by another process. If the parent - -- process is not alive then the server should exit (see exit notification) - -- its process. - processId = uv.os_getpid(), - -- Information about the client - -- since 3.15.0 - clientInfo = { - name = 'Neovim', - version = tostring(vim.version()), - }, - -- The rootPath of the workspace. Is null if no folder is open. - -- - -- @deprecated in favour of rootUri. - rootPath = root_path or vim.NIL, - -- The rootUri of the workspace. Is null if no folder is open. If both - -- `rootPath` and `rootUri` are set `rootUri` wins. - rootUri = root_uri or vim.NIL, - -- The workspace folders configured in the client when the server starts. - -- This property is only available if the client supports workspace folders. - -- It can be `null` if the client supports workspace folders but none are - -- configured. - workspaceFolders = workspace_folders or vim.NIL, - -- User provided initialization options. - initializationOptions = config.init_options, - -- The capabilities provided by the client (editor or tool) - capabilities = config.capabilities, - -- The initial trace setting. If omitted trace is disabled ("off"). - -- trace = "off" | "messages" | "verbose"; - trace = valid_traces[config.trace] or 'off', - } - if config.before_init then - local status, err = pcall(config.before_init, initialize_params, config) - if not status then - write_error(lsp.client_errors.BEFORE_INIT_CALLBACK_ERROR, err) - end - end - - --- @param method string - --- @param opts? {bufnr: integer?} - client.supports_method = function(method, opts) - opts = opts or {} - local required_capability = lsp._request_name_to_capability[method] - -- if we don't know about the method, assume that the client supports it. - if not required_capability then - return true - end - if vim.tbl_get(client.server_capabilities, unpack(required_capability)) then - return true - else - if client.dynamic_capabilities:supports_registration(method) then - return client.dynamic_capabilities:supports(method, opts) - end - return false - end - end - - if log.trace() then - log.trace(log_prefix, 'initialize_params', initialize_params) - end - rpc.request('initialize', initialize_params, function(init_err, result) - assert(not init_err, tostring(init_err)) - assert(result, 'server sent empty result') - rpc.notify('initialized', vim.empty_dict()) - client.initialized = true - uninitialized_clients[client_id] = nil - client.workspace_folders = workspace_folders - - -- These are the cleaned up capabilities we use for dynamically deciding - -- when to send certain events to clients. - client.server_capabilities = - assert(result.capabilities, "initialize result doesn't contain capabilities") - client.server_capabilities = assert(protocol.resolve_capabilities(client.server_capabilities)) - - if client.server_capabilities.positionEncoding then - client.offset_encoding = client.server_capabilities.positionEncoding - end - - if next(config.settings) then - client.notify(ms.workspace_didChangeConfiguration, { settings = config.settings }) - end - - if config.on_init then - local status, err = pcall(config.on_init, client, result) - if not status then - write_error(lsp.client_errors.ON_INIT_CALLBACK_ERROR, err) - end - end - if log.info() then - log.info( - log_prefix, - 'server_capabilities', - { server_capabilities = client.server_capabilities } - ) - end - - -- Only assign after initialized. - active_clients[client_id] = client - -- If we had been registered before we start, then send didOpen This can - -- happen if we attach to buffers before initialize finishes or if - -- someone restarts a client. - for bufnr, client_ids in pairs(all_buffer_active_clients) do - if client_ids[client_id] then - client._on_attach(bufnr) - end - end - end) - end - - ---@nodoc - --- Sends a request to the server. - --- - --- This is a thin wrapper around {client.rpc.request} with some additional - --- checks for capabilities and handler availability. - --- - ---@param method string LSP method name. - ---@param params table|nil LSP request params. - ---@param handler lsp.Handler|nil Response |lsp-handler| for this method. - ---@param bufnr integer Buffer handle (0 for current). - ---@return boolean status, integer|nil request_id {status} is a bool indicating - ---whether the request was successful. If it is `false`, then it will - ---always be `false` (the client has shutdown). If it was - ---successful, then it will return {request_id} as the - ---second result. You can use this with `client.cancel_request(request_id)` - ---to cancel the-request. - ---@see |vim.lsp.buf_request_all()| - function client.request(method, params, handler, bufnr) - if not handler then - handler = assert( - resolve_handler(method), - string.format('not found: %q request handler for client %q.', method, client.name) - ) - end - -- Ensure pending didChange notifications are sent so that the server doesn't operate on a stale state - changetracking.flush(client, bufnr) - local version = util.buf_versions[bufnr] - bufnr = resolve_bufnr(bufnr) - if log.debug() then - log.debug(log_prefix, 'client.request', client_id, method, params, handler, bufnr) - end - local success, request_id = rpc.request(method, params, function(err, result) - local context = { - method = method, - client_id = client_id, - bufnr = bufnr, - params = params, - version = version, - } - handler(err, result, context) - end, function(request_id) - local request = client.requests[request_id] - request.type = 'complete' - nvim_exec_autocmds('LspRequest', { - buffer = api.nvim_buf_is_valid(bufnr) and bufnr or nil, - modeline = false, - data = { client_id = client_id, request_id = request_id, request = request }, - }) - client.requests[request_id] = nil - end) - - if success and request_id then - local request = { type = 'pending', bufnr = bufnr, method = method } - client.requests[request_id] = request - nvim_exec_autocmds('LspRequest', { - buffer = bufnr, - modeline = false, - data = { client_id = client_id, request_id = request_id, request = request }, - }) - end - - return success, request_id - end - - ---@private - --- Sends a request to the server and synchronously waits for the response. - --- - --- This is a wrapper around {client.request} - --- - ---@param method (string) LSP method name. - ---@param params (table) LSP request params. - ---@param timeout_ms (integer|nil) Maximum time in milliseconds to wait for - --- a result. Defaults to 1000 - ---@param bufnr (integer) Buffer handle (0 for current). - ---@return {err: lsp.ResponseError|nil, result:any}|nil, string|nil err # a dictionary, where - --- `err` and `result` come from the |lsp-handler|. - --- On timeout, cancel or error, returns `(nil, err)` where `err` is a - --- string describing the failure reason. If the request was unsuccessful - --- returns `nil`. - ---@see |vim.lsp.buf_request_sync()| - function client.request_sync(method, params, timeout_ms, bufnr) - local request_result = nil - local function _sync_handler(err, result) - request_result = { err = err, result = result } - end - - local success, request_id = client.request(method, params, _sync_handler, bufnr) - if not success then - return nil - end - - local wait_result, reason = vim.wait(timeout_ms or 1000, function() - return request_result ~= nil - end, 10) - - if not wait_result then - if request_id then - client.cancel_request(request_id) - end - return nil, wait_result_reason[reason] - end - return request_result - end - - ---@nodoc - --- Sends a notification to an LSP server. - --- - ---@param method string LSP method name. - ---@param params table|nil LSP request params. - ---@return boolean status true if the notification was successful. - ---If it is false, then it will always be false - ---(the client has shutdown). - function client.notify(method, params) - if method ~= ms.textDocument_didChange then - changetracking.flush(client) - end - - local client_active = rpc.notify(method, params) - - if client_active then - vim.schedule(function() - nvim_exec_autocmds('LspNotify', { - modeline = false, - data = { - client_id = client.id, - method = method, - params = params, - }, - }) - end) - end - - return client_active - end - - ---@nodoc - --- Cancels a request with a given request id. - --- - ---@param id (integer) id of request to cancel - ---@return boolean status true if notification was successful. false otherwise - ---@see |vim.lsp.client.notify()| - function client.cancel_request(id) - validate({ id = { id, 'n' } }) - local request = client.requests[id] - if request and request.type == 'pending' then - request.type = 'cancel' - nvim_exec_autocmds('LspRequest', { - buffer = request.bufnr, - modeline = false, - data = { client_id = client_id, request_id = id, request = request }, - }) - end - return rpc.notify(ms.dollar_cancelRequest, { id = id }) - end - - -- Track this so that we can escalate automatically if we've already tried a - -- graceful shutdown - local graceful_shutdown_failed = false - - ---@nodoc - --- Stops 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. - --- - ---@param force boolean|nil - function client.stop(force) - if rpc.is_closing() then - return - end - if force or not client.initialized or graceful_shutdown_failed then - rpc.terminate() - return - end - -- Sending a signal after a process has exited is acceptable. - rpc.request(ms.shutdown, nil, function(err, _) - if err == nil then - rpc.notify(ms.exit) - else - -- If there was an error in the shutdown request, then term to be safe. - rpc.terminate() - graceful_shutdown_failed = true - end - end) - end - - ---@private - --- Checks whether a client is stopped. - --- - ---@return boolean # true if client is stopped or in the process of being - ---stopped; false otherwise - function client.is_stopped() - return rpc.is_closing() - end - - ---@private - --- Execute a lsp command, either via client command function (if available) - --- or via workspace/executeCommand (if supported by the server) - --- - ---@param command lsp.Command - ---@param context? {bufnr: integer} - ---@param handler? lsp.Handler only called if a server command - function client._exec_cmd(command, context, handler) - context = vim.deepcopy(context or {}, true) --[[@as lsp.HandlerContext]] - context.bufnr = context.bufnr or api.nvim_get_current_buf() - context.client_id = client.id - local cmdname = command.command - local fn = client.commands[cmdname] or lsp.commands[cmdname] - if fn then - fn(command, context) - return - end - - local command_provider = client.server_capabilities.executeCommandProvider - local commands = type(command_provider) == 'table' and command_provider.commands or {} - if not vim.list_contains(commands, cmdname) then - vim.notify_once( - string.format( - 'Language server `%s` does not support command `%s`. This command may require a client extension.', - client.name, - cmdname - ), - vim.log.levels.WARN - ) - return - end - -- Not using command directly to exclude extra properties, - -- see https://github.com/python-lsp/python-lsp-server/issues/146 - local params = { - command = command.command, - arguments = command.arguments, - } - client.request(ms.workspace_executeCommand, params, handler, context.bufnr) - end - - ---@private - --- Runs the on_attach function from the client's config if it was defined. - ---@param bufnr integer Buffer number - function client._on_attach(bufnr) - text_document_did_open_handler(bufnr, client) - - lsp._set_defaults(client, bufnr) - - nvim_exec_autocmds('LspAttach', { - buffer = bufnr, - modeline = false, - data = { client_id = client.id }, - }) - - if config.on_attach then - local status, err = pcall(config.on_attach, client, bufnr) - if not status then - write_error(lsp.client_errors.ON_ATTACH_ERROR, err) + client:initialize(function() + uninitialized_clients[client_id] = nil + -- Only assign after initialized. + active_clients[client_id] = client + -- If we had been registered before we start, then send didOpen This can + -- happen if we attach to buffers before initialize finishes or if + -- someone restarts a client. + for bufnr, client_ids in pairs(all_buffer_active_clients) do + if client_ids[client_id] then + client.on_attach(bufnr) end end - - -- schedule the initialization of semantic tokens to give the above - -- on_attach and LspAttach callbacks the ability to schedule wrap the - -- opt-out (deleting the semanticTokensProvider from capabilities) - vim.schedule(function() - if vim.tbl_get(client.server_capabilities, 'semanticTokensProvider', 'full') then - lsp.semantic_tokens.start(bufnr, client.id) - end - end) - - client.attached_buffers[bufnr] = true - end - - initialize() + end) return client_id end @@ -1564,7 +1101,7 @@ function lsp.buf_attach_client(bufnr, client_id) if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then client.notify(ms.textDocument_didClose, params) end - text_document_did_open_handler(bufnr, client) + client:_text_document_did_open_handler(bufnr) end end, on_detach = function() @@ -1596,7 +1133,7 @@ function lsp.buf_attach_client(bufnr, client_id) -- Send didOpen for the client if it is initialized. If it isn't initialized -- then it will send didOpen on initialize. if client then - client._on_attach(bufnr) + client:_on_attach(bufnr) end return true end diff --git a/runtime/lua/vim/lsp/_dynamic.lua b/runtime/lua/vim/lsp/_dynamic.lua index 3c9dee2c69..8b8f3bdc38 100644 --- a/runtime/lua/vim/lsp/_dynamic.lua +++ b/runtime/lua/vim/lsp/_dynamic.lua @@ -6,6 +6,7 @@ local glob = vim.glob local M = {} --- @param client_id number +--- @return lsp.DynamicCapabilities function M.new(client_id) return setmetatable({ capabilities = {}, @@ -37,7 +38,7 @@ function M:register(registrations) end --- @param unregisterations lsp.Unregistration[] ---- @private +--- @package function M:unregister(unregisterations) for _, unreg in ipairs(unregisterations) do local method = unreg.method @@ -77,7 +78,7 @@ end --- @param method string --- @param opts? {bufnr: integer?} ---- @private +--- @package function M:supports(method, opts) return self:get(method, opts) ~= nil end diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index d67b2ac8ea..7fc5286a78 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -652,7 +652,7 @@ local function on_code_action_results(results, opts) end if action.command then local command = type(action.command) == 'table' and action.command or action - client._exec_cmd(command, ctx) + client:_exec_cmd(command, ctx) end end diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua new file mode 100644 index 0000000000..2daf564f63 --- /dev/null +++ b/runtime/lua/vim/lsp/client.lua @@ -0,0 +1,663 @@ +local uv = vim.uv +local api = vim.api +local lsp = vim.lsp +local log = lsp.log +local ms = lsp.protocol.Methods +local changetracking = lsp._changetracking + +--- @class lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}> +--- @field pending table + +--- @class lsp.Client +--- +--- The id allocated to the client. +--- @field id integer +--- +--- 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. +--- @field name string +--- +--- RPC client object, for low level interaction with the client. +--- See |vim.lsp.rpc.start()|. +--- @field rpc vim.lsp.rpc.PublicClient +--- +--- The encoding used for communicating with the server. You can modify this in +--- the `config`'s `on_init` method before text is sent to the server. +--- @field offset_encoding string +--- +--- The handlers used by the client as described in |lsp-handler|. +--- @field handlers table +--- +--- The current pending requests in flight to the server. Entries are key-value +--- pairs with the key being the request ID while the value is a table with +--- `type`, `bufnr`, and `method` key-value pairs. `type` is either "pending" +--- for an active request, or "cancel" for a cancel request. It will be +--- "complete" ephemerally while executing |LspRequest| autocmds when replies +--- are received from the server. +--- @field requests table +--- +--- copy of the table that was passed by the user +--- to |vim.lsp.start_client()|. +--- @field config lsp.ClientConfig +--- +--- Response from the server sent on +--- initialize` describing the server's capabilities. +--- @field server_capabilities lsp.ServerCapabilities +--- +--- A ring buffer (|vim.ringbuf()|) containing progress messages +--- sent by the server. +--- @field progress lsp.Client.Progress +--- +--- @field initialized true? +--- @field workspace_folders lsp.WorkspaceFolder[]? +--- @field attached_buffers table +--- @field commands table +--- @field private _log_prefix string +--- Track this so that we can escalate automatically if we've already tried a +--- graceful shutdown +--- @field private _graceful_shutdown_failed true? +--- +--- @field dynamic_capabilities lsp.DynamicCapabilities +--- +--- Sends a request to the server. +--- This is a thin wrapper around {client.rpc.request} with some additional +--- checking. +--- If {handler} is not specified, If one is not found there, then an error +--- will occur. Returns: {status}, {[client_id]}. {status} is a boolean +--- indicating if the notification was successful. If it is `false`, then it +--- will always be `false` (the client has shutdown). +--- If {status} is `true`, the function returns {request_id} as the second +--- result. You can use this with `client.cancel_request(request_id)` to cancel +--- the request. +--- @field request fun(method: string, params: table?, handler: lsp.Handler?, bufnr: integer): boolean, integer? +--- +--- Sends a request to the server and synchronously waits for the response. +--- This is a wrapper around {client.request} +--- Returns: { err=err, result=result }, a dictionary, where `err` and `result` +--- come from the |lsp-handler|. On timeout, cancel or error, returns `(nil, +--- err)` where `err` is a string describing the failure reason. If the request +--- was unsuccessful returns `nil`. +--- @field request_sync fun(method: string, params: table?, timeout_ms: integer?, bufnr: integer): {err: lsp.ResponseError|nil, result:any}|nil, string|nil err # a dictionary, where +--- +--- Sends a notification to an LSP server. +--- Returns: a boolean to indicate if the notification was successful. If +--- it is false, then it will always be false (the client has shutdown). +--- @field notify fun(method: string, params: table?): boolean +--- +--- Cancels a request with a given request id. +--- Returns: same as `notify()`. +--- @field cancel_request fun(id: integer): boolean +--- +--- Stops 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. +--- @field stop fun(force?: boolean) +--- +--- Runs the on_attach function from the client's config if it was defined. +--- Useful for buffer-local setup. +--- @field on_attach fun(bufnr: integer) +--- +--- Checks if a client supports a given method. +--- Always returns true for unknown off-spec methods. +--- [opts] is a optional `{bufnr?: integer}` table. +--- Some language server capabilities can be file specific. +--- @field supports_method fun(method: string, opts?: {bufnr: integer?}): boolean +--- +--- Checks whether a client is stopped. +--- Returns: true if the client is fully stopped. +--- @field is_stopped fun(): boolean +local Client = {} +Client.__index = Client + +--- @param cls table +--- @param meth any +--- @return function +local function method_wrapper(cls, meth) + return function(...) + return meth(cls, ...) + end +end + +--- @package +--- @param id integer +--- @param rpc vim.lsp.rpc.PublicClient +--- @param handlers table +--- @param offset_encoding string +--- @param config lsp.ClientConfig +--- @return lsp.Client +function Client.new(id, rpc, handlers, offset_encoding, config) + local name = config.name + + --- @class lsp.Client + local self = { + id = id, + config = config, + handlers = handlers, + rpc = rpc, + offset_encoding = offset_encoding, + name = name, + _log_prefix = string.format('LSP[%s]', name), + requests = {}, + commands = config.commands or {}, + attached_buffers = {}, + server_capabilities = {}, + dynamic_capabilities = vim.lsp._dynamic.new(id), + + --- Contains $/progress report messages. + --- They have the format {token: integer|string, value: any} + --- For "work done progress", value will be one of: + --- - lsp.WorkDoneProgressBegin, + --- - lsp.WorkDoneProgressReport (extended with title from Begin) + --- - lsp.WorkDoneProgressEnd (extended with title from Begin) + progress = vim.ringbuf(50) --[[@as lsp.Client.Progress]], + + --- @deprecated use client.progress instead + messages = { name = name, messages = {}, progress = {}, status = {} }, + } + + self.request = method_wrapper(self, Client._request) + self.request_sync = method_wrapper(self, Client._request_sync) + self.notify = method_wrapper(self, Client._notify) + self.cancel_request = method_wrapper(self, Client._cancel_request) + self.stop = method_wrapper(self, Client._stop) + self.is_stopped = method_wrapper(self, Client._is_stopped) + self.on_attach = method_wrapper(self, Client._on_attach) + self.supports_method = method_wrapper(self, Client._supports_method) + + ---@type table title of unfinished progress sequences by token + self.progress.pending = {} + + return setmetatable(self, Client) +end + +--- @private +--- @param cb fun() +function Client:initialize(cb) + local valid_traces = { + off = 'off', + messages = 'messages', + verbose = 'verbose', + } + + local config = self.config + + local workspace_folders --- @type lsp.WorkspaceFolder[]? + local root_uri --- @type string? + local root_path --- @type string? + if config.workspace_folders or config.root_dir then + if config.root_dir and not config.workspace_folders then + workspace_folders = { + { + uri = vim.uri_from_fname(config.root_dir), + name = string.format('%s', config.root_dir), + }, + } + else + workspace_folders = config.workspace_folders + end + root_uri = workspace_folders[1].uri + root_path = vim.uri_to_fname(root_uri) + else + workspace_folders = nil + root_uri = nil + root_path = nil + end + + local initialize_params = { + -- The process Id of the parent process that started the server. Is null if + -- the process has not been started by another process. If the parent + -- process is not alive then the server should exit (see exit notification) + -- its process. + processId = uv.os_getpid(), + -- Information about the client + -- since 3.15.0 + clientInfo = { + name = 'Neovim', + version = tostring(vim.version()), + }, + -- The rootPath of the workspace. Is null if no folder is open. + -- + -- @deprecated in favour of rootUri. + rootPath = root_path or vim.NIL, + -- The rootUri of the workspace. Is null if no folder is open. If both + -- `rootPath` and `rootUri` are set `rootUri` wins. + rootUri = root_uri or vim.NIL, + -- The workspace folders configured in the client when the server starts. + -- This property is only available if the client supports workspace folders. + -- It can be `null` if the client supports workspace folders but none are + -- configured. + workspaceFolders = workspace_folders or vim.NIL, + -- User provided initialization options. + initializationOptions = config.init_options, + -- The capabilities provided by the client (editor or tool) + capabilities = config.capabilities, + -- The initial trace setting. If omitted trace is disabled ("off"). + -- trace = "off" | "messages" | "verbose"; + trace = valid_traces[config.trace] or 'off', + } + if config.before_init then + --- @type boolean, string? + local status, err = pcall(config.before_init, initialize_params, config) + if not status then + self:write_error(lsp.client_errors.BEFORE_INIT_CALLBACK_ERROR, err) + end + end + + if log.trace() then + log.trace(self._log_prefix, 'initialize_params', initialize_params) + end + + local rpc = self.rpc + + rpc.request('initialize', initialize_params, function(init_err, result) + assert(not init_err, tostring(init_err)) + assert(result, 'server sent empty result') + rpc.notify('initialized', vim.empty_dict()) + self.initialized = true + self.workspace_folders = workspace_folders + + -- These are the cleaned up capabilities we use for dynamically deciding + -- when to send certain events to clients. + self.server_capabilities = + assert(result.capabilities, "initialize result doesn't contain capabilities") + self.server_capabilities = assert(lsp.protocol.resolve_capabilities(self.server_capabilities)) + + if self.server_capabilities.positionEncoding then + self.offset_encoding = self.server_capabilities.positionEncoding + end + + if next(config.settings) then + self:_notify(ms.workspace_didChangeConfiguration, { settings = config.settings }) + end + + if config.on_init then + --- @type boolean, string? + local status, err = pcall(config.on_init, self, result) + if not status then + self:write_error(lsp.client_errors.ON_INIT_CALLBACK_ERROR, err) + end + end + if log.info() then + log.info( + self._log_prefix, + 'server_capabilities', + { server_capabilities = self.server_capabilities } + ) + end + + cb() + end) +end + +--- @private +--- Returns the handler associated with an LSP method. +--- Returns the default handler if the user hasn't set a custom one. +--- +--- @param method (string) LSP method name +--- @return lsp.Handler|nil handler for the given method, if defined, or the default from |vim.lsp.handlers| +function Client:_resolve_handler(method) + return self.handlers[method] or lsp.handlers[method] +end + +--- Returns the buffer number for the given {bufnr}. +--- +--- @param bufnr (integer|nil) Buffer number to resolve. Defaults to current buffer +--- @return integer bufnr +local function resolve_bufnr(bufnr) + vim.validate({ bufnr = { bufnr, 'n', true } }) + if bufnr == nil or bufnr == 0 then + return api.nvim_get_current_buf() + end + return bufnr +end + +--- @private +--- Sends a request to the server. +--- +--- This is a thin wrapper around {client.rpc.request} with some additional +--- checks for capabilities and handler availability. +--- +--- @param method string LSP method name. +--- @param params table|nil LSP request params. +--- @param handler lsp.Handler|nil Response |lsp-handler| for this method. +--- @param bufnr integer Buffer handle (0 for current). +--- @return boolean status, integer|nil request_id {status} is a bool indicating +--- whether the request was successful. If it is `false`, then it will +--- always be `false` (the client has shutdown). If it was +--- successful, then it will return {request_id} as the +--- second result. You can use this with `client.cancel_request(request_id)` +--- to cancel the-request. +--- @see |vim.lsp.buf_request_all()| +function Client:_request(method, params, handler, bufnr) + if not handler then + handler = assert( + self:_resolve_handler(method), + string.format('not found: %q request handler for client %q.', method, self.name) + ) + end + -- Ensure pending didChange notifications are sent so that the server doesn't operate on a stale state + changetracking.flush(self, bufnr) + local version = lsp.util.buf_versions[bufnr] + bufnr = resolve_bufnr(bufnr) + if log.debug() then + log.debug(self._log_prefix, 'client.request', self.id, method, params, handler, bufnr) + end + local success, request_id = self.rpc.request(method, params, function(err, result) + local context = { + method = method, + client_id = self.id, + bufnr = bufnr, + params = params, + version = version, + } + handler(err, result, context) + end, function(request_id) + local request = self.requests[request_id] + request.type = 'complete' + api.nvim_exec_autocmds('LspRequest', { + buffer = api.nvim_buf_is_valid(bufnr) and bufnr or nil, + modeline = false, + data = { client_id = self.id, request_id = request_id, request = request }, + }) + self.requests[request_id] = nil + end) + + if success and request_id then + local request = { type = 'pending', bufnr = bufnr, method = method } + self.requests[request_id] = request + api.nvim_exec_autocmds('LspRequest', { + buffer = bufnr, + modeline = false, + data = { client_id = self.id, request_id = request_id, request = request }, + }) + end + + return success, request_id +end + +-- TODO(lewis6991): duplicated from lsp.lua +local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'error' } + +-- TODO(lewis6991): duplicated from lsp.lua +--- Concatenates and writes a list of strings to the Vim error buffer. +--- +---@param ... string List to write to the buffer +local function err_message(...) + api.nvim_err_writeln(table.concat(vim.tbl_flatten({ ... }))) + api.nvim_command('redraw') +end + +--- @private +--- Sends a request to the server and synchronously waits for the response. +--- +--- This is a wrapper around {client.request} +--- +--- @param method (string) LSP method name. +--- @param params (table) LSP request params. +--- @param timeout_ms (integer|nil) Maximum time in milliseconds to wait for +--- a result. Defaults to 1000 +--- @param bufnr (integer) Buffer handle (0 for current). +--- @return {err: lsp.ResponseError|nil, result:any}|nil, string|nil err # a dictionary, where +--- `err` and `result` come from the |lsp-handler|. +--- On timeout, cancel or error, returns `(nil, err)` where `err` is a +--- string describing the failure reason. If the request was unsuccessful +--- returns `nil`. +--- @see |vim.lsp.buf_request_sync()| +function Client:_request_sync(method, params, timeout_ms, bufnr) + local request_result = nil + local function _sync_handler(err, result) + request_result = { err = err, result = result } + end + + local success, request_id = self:_request(method, params, _sync_handler, bufnr) + if not success then + return nil + end + + local wait_result, reason = vim.wait(timeout_ms or 1000, function() + return request_result ~= nil + end, 10) + + if not wait_result then + if request_id then + self:_cancel_request(request_id) + end + return nil, wait_result_reason[reason] + end + return request_result +end + +--- @private +--- Sends a notification to an LSP server. +--- +--- @param method string LSP method name. +--- @param params table|nil LSP request params. +--- @return boolean status true if the notification was successful. +--- If it is false, then it will always be false +--- (the client has shutdown). +function Client:_notify(method, params) + if method ~= ms.textDocument_didChange then + changetracking.flush(self) + end + + local client_active = self.rpc.notify(method, params) + + if client_active then + vim.schedule(function() + api.nvim_exec_autocmds('LspNotify', { + modeline = false, + data = { + client_id = self.id, + method = method, + params = params, + }, + }) + end) + end + + return client_active +end + +--- @private +--- Cancels a request with a given request id. +--- +--- @param id (integer) id of request to cancel +--- @return boolean status true if notification was successful. false otherwise +--- @see |vim.lsp.client.notify()| +function Client:_cancel_request(id) + vim.validate({ id = { id, 'n' } }) + local request = self.requests[id] + if request and request.type == 'pending' then + request.type = 'cancel' + api.nvim_exec_autocmds('LspRequest', { + buffer = request.bufnr, + modeline = false, + data = { client_id = self.id, request_id = id, request = request }, + }) + end + return self.rpc.notify(ms.dollar_cancelRequest, { id = id }) +end + +--- @nodoc +--- Stops 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. +--- +--- @param force boolean|nil +function Client:_stop(force) + local rpc = self.rpc + + if rpc.is_closing() then + return + end + + if force or not self.initialized or self._graceful_shutdown_failed then + rpc.terminate() + return + end + + -- Sending a signal after a process has exited is acceptable. + rpc.request(ms.shutdown, nil, function(err, _) + if err == nil then + rpc.notify(ms.exit) + else + -- If there was an error in the shutdown request, then term to be safe. + rpc.terminate() + self._graceful_shutdown_failed = true + end + end) +end + +--- @private +--- Checks whether a client is stopped. +--- +--- @return boolean # true if client is stopped or in the process of being +--- stopped; false otherwise +function Client:_is_stopped() + return self.rpc.is_closing() +end + +--- @private +--- Execute a lsp command, either via client command function (if available) +--- or via workspace/executeCommand (if supported by the server) +--- +--- @param command lsp.Command +--- @param context? {bufnr: integer} +--- @param handler? lsp.Handler only called if a server command +function Client:_exec_cmd(command, context, handler) + context = vim.deepcopy(context or {}, true) --[[@as lsp.HandlerContext]] + context.bufnr = context.bufnr or api.nvim_get_current_buf() + context.client_id = self.id + local cmdname = command.command + local fn = self.commands[cmdname] or lsp.commands[cmdname] + if fn then + fn(command, context) + return + end + + local command_provider = self.server_capabilities.executeCommandProvider + local commands = type(command_provider) == 'table' and command_provider.commands or {} + if not vim.list_contains(commands, cmdname) then + vim.notify_once( + string.format( + 'Language server `%s` does not support command `%s`. This command may require a client extension.', + self.name, + cmdname + ), + vim.log.levels.WARN + ) + return + end + -- Not using command directly to exclude extra properties, + -- see https://github.com/python-lsp/python-lsp-server/issues/146 + local params = { + command = command.command, + arguments = command.arguments, + } + self.request(ms.workspace_executeCommand, params, handler, context.bufnr) +end + +--- @package +--- Default handler for the 'textDocument/didOpen' LSP notification. +--- +--- @param bufnr integer Number of the buffer, or 0 for current +function Client:_text_document_did_open_handler(bufnr) + changetracking.init(self, bufnr) + if not vim.tbl_get(self.server_capabilities, 'textDocumentSync', 'openClose') then + return + end + if not api.nvim_buf_is_loaded(bufnr) then + return + end + local filetype = vim.bo[bufnr].filetype + + local params = { + textDocument = { + version = 0, + uri = vim.uri_from_bufnr(bufnr), + languageId = self.config.get_language_id(bufnr, filetype), + text = lsp._buf_get_full_text(bufnr), + }, + } + self.notify(ms.textDocument_didOpen, params) + lsp.util.buf_versions[bufnr] = params.textDocument.version + + -- Next chance we get, we should re-do the diagnostics + vim.schedule(function() + -- Protect against a race where the buffer disappears + -- between `did_open_handler` and the scheduled function firing. + if api.nvim_buf_is_valid(bufnr) then + local namespace = vim.lsp.diagnostic.get_namespace(self.id) + vim.diagnostic.show(namespace, bufnr) + end + end) +end + +--- @private +--- Runs the on_attach function from the client's config if it was defined. +--- @param bufnr integer Buffer number +function Client:_on_attach(bufnr) + self:_text_document_did_open_handler(bufnr) + + lsp._set_defaults(self, bufnr) + + api.nvim_exec_autocmds('LspAttach', { + buffer = bufnr, + modeline = false, + data = { client_id = self.id }, + }) + + if self.config.on_attach then + --- @type boolean, string? + local status, err = pcall(self.config.on_attach, self, bufnr) + if not status then + self:write_error(lsp.client_errors.ON_ATTACH_ERROR, err) + end + end + + -- schedule the initialization of semantic tokens to give the above + -- on_attach and LspAttach callbacks the ability to schedule wrap the + -- opt-out (deleting the semanticTokensProvider from capabilities) + vim.schedule(function() + if vim.tbl_get(self.server_capabilities, 'semanticTokensProvider', 'full') then + lsp.semantic_tokens.start(bufnr, self.id) + end + end) + + self.attached_buffers[bufnr] = true +end + +--- @private +--- Logs the given error to the LSP log and to the error buffer. +--- @param code integer Error code +--- @param err any Error arguments +function Client:write_error(code, err) + if log.error() then + log.error(self._log_prefix, 'on_error', { code = lsp.client_errors[code], err = err }) + end + err_message(self._log_prefix, ': Error ', lsp.client_errors[code], ': ', vim.inspect(err)) +end + +--- @param method string +--- @param opts? {bufnr: integer?} +function Client:_supports_method(method, opts) + opts = opts or {} + local required_capability = lsp._request_name_to_capability[method] + -- if we don't know about the method, assume that the client supports it. + if not required_capability then + return true + end + if vim.tbl_get(self.server_capabilities, unpack(required_capability)) then + return true + else + if self.dynamic_capabilities:supports_registration(method) then + return self.dynamic_capabilities:supports(method, opts) + end + return false + end +end + +return Client diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index 199da288f4..a045a6bad4 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -48,7 +48,7 @@ local function execute_lens(lens, bufnr, client_id) local client = vim.lsp.get_client_by_id(client_id) assert(client, 'Client is required to execute lens, client_id=' .. client_id) - client._exec_cmd(lens.command, { bufnr = bufnr }, function(...) + client:_exec_cmd(lens.command, { bufnr = bufnr }, function(...) vim.lsp.handlers[ms.workspace_executeCommand](...) M.refresh() end) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index fa7690e41e..dd0f7c2e1e 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -895,6 +895,7 @@ do ---@field private _idx_read integer ---@field private _idx_write integer ---@field private _size integer + ---@overload fun(self): table? local Ringbuf = {} --- Clear all items -- cgit From 5785c32f1115833cf69ec9062c5bc8907360aab0 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 8 Feb 2024 07:34:38 +0800 Subject: fix(lsp): set fallback client name properly --- runtime/lua/vim/lsp/client.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index 2daf564f63..36c3a4225e 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -127,7 +127,7 @@ end --- @param config lsp.ClientConfig --- @return lsp.Client function Client.new(id, rpc, handlers, offset_encoding, config) - local name = config.name + local name = config.name or tostring(id) --- @class lsp.Client local self = { -- cgit From b162adbb7ca4f980e938a4a06a49218a9ed496cf Mon Sep 17 00:00:00 2001 From: nikolightsaber <103886134+nikolightsaber@users.noreply.github.com> Date: Thu, 8 Feb 2024 11:59:31 +0100 Subject: feat(api): pass 0 to nvim_get_chan_info for current channel (#27321) Getting current channel info was kind of annoying via RPC. Two functions had to be called: 1. `nvim_get_api_info` which returns `[channel_id, meta_data]`. - This results in `channel_id = api.nvim_get_api_info()[0]`. - Here the meta_data is sent but never used. 2. Finally call `nvim_get_chan_info(channel_id)`. This commit reduces the need for `nvim_get_api_info` as passing 0 returns current channel info. --- runtime/lua/vim/_meta/api.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 77a29cb4c1..8b29727196 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1158,7 +1158,7 @@ function vim.api.nvim_get_autocmds(opts) end --- Gets information about a channel. --- ---- @param chan integer +--- @param chan integer channel_id, or 0 for current channel --- @return table function vim.api.nvim_get_chan_info(chan) end -- cgit From 1f9da3d0835af2cfe937de250c2cde3a59e1677e Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 8 Feb 2024 09:24:47 +0000 Subject: refactor(lsp): tidy up logging --- runtime/lua/vim/lsp.lua | 32 ++---- runtime/lua/vim/lsp/client.lua | 25 ++--- runtime/lua/vim/lsp/codelens.lua | 4 +- runtime/lua/vim/lsp/diagnostic.lua | 4 +- runtime/lua/vim/lsp/handlers.lua | 9 +- runtime/lua/vim/lsp/inlay_hint.lua | 4 +- runtime/lua/vim/lsp/log.lua | 206 ++++++++++++++++++------------------- runtime/lua/vim/lsp/rpc.lua | 42 +++----- 8 files changed, 140 insertions(+), 186 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index dc50ab0267..7d8b7e50a3 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -798,9 +798,7 @@ function lsp.start_client(config) ---@param method (string) LSP method name ---@param params (table) The parameters for that method. function dispatch.notification(method, params) - if log.trace() then - log.trace('notification', method, params) - end + log.trace('notification', method, params) local handler = resolve_handler(method) if handler then -- Method name is provided here for convenience. @@ -816,19 +814,13 @@ function lsp.start_client(config) ---@return any result ---@return lsp.ResponseError error code and message set in case an exception happens during the request. function dispatch.server_request(method, params) - if log.trace() then - log.trace('server_request', method, params) - end + log.trace('server_request', method, params) local handler = resolve_handler(method) if handler then - if log.trace() then - log.trace('server_request: found handler for', method) - end + log.trace('server_request: found handler for', method) return handler(nil, params, { method = method, client_id = client_id }) end - if log.warn() then - log.warn('server_request: no handler found for', method) - end + log.warn('server_request: no handler found for', method) return nil, lsp.rpc_response_error(protocol.ErrorCodes.MethodNotFound) end @@ -836,9 +828,7 @@ function lsp.start_client(config) --- @param code integer Error code --- @param err any Error arguments local function write_error(code, err) - if log.error() then - log.error(log_prefix, 'on_error', { code = lsp.client_errors[code], err = err }) - end + log.error(log_prefix, 'on_error', { code = lsp.client_errors[code], err = err }) err_message(log_prefix, ': Error ', lsp.client_errors[code], ': ', vim.inspect(err)) end @@ -854,9 +844,7 @@ function lsp.start_client(config) if config.on_error then local status, usererr = pcall(config.on_error, code, err) if not status then - if log.error() then - log.error(log_prefix, 'user on_error failed', { err = usererr }) - end + log.error(log_prefix, 'user on_error failed', { err = usererr }) err_message(log_prefix, ' user on_error failed: ', tostring(usererr)) end end @@ -1042,9 +1030,7 @@ function lsp.buf_attach_client(bufnr, client_id) }) bufnr = resolve_bufnr(bufnr) if not api.nvim_buf_is_loaded(bufnr) then - if log.warn() then - log.warn(string.format('buf_attach_client called on unloaded buffer (id: %d): ', bufnr)) - end + log.warn(string.format('buf_attach_client called on unloaded buffer (id: %d): ', bufnr)) return false end local buffer_client_ids = all_buffer_active_clients[bufnr] @@ -1504,9 +1490,7 @@ end --- - findstart=0: column where the completion starts, or -2 or -3 --- - findstart=1: list of matches (actually just calls |complete()|) function lsp.omnifunc(findstart, base) - if log.debug() then - log.debug('omnifunc.findstart', { findstart = findstart, base = base }) - end + log.debug('omnifunc.findstart', { findstart = findstart, base = base }) return vim.lsp._completion.omnifunc(findstart, base) end diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index 36c3a4225e..0bcbb35be6 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -244,9 +244,7 @@ function Client:initialize(cb) end end - if log.trace() then - log.trace(self._log_prefix, 'initialize_params', initialize_params) - end + log.trace(self._log_prefix, 'initialize_params', initialize_params) local rpc = self.rpc @@ -278,13 +276,12 @@ function Client:initialize(cb) self:write_error(lsp.client_errors.ON_INIT_CALLBACK_ERROR, err) end end - if log.info() then - log.info( - self._log_prefix, - 'server_capabilities', - { server_capabilities = self.server_capabilities } - ) - end + + log.info( + self._log_prefix, + 'server_capabilities', + { server_capabilities = self.server_capabilities } + ) cb() end) @@ -340,9 +337,7 @@ function Client:_request(method, params, handler, bufnr) changetracking.flush(self, bufnr) local version = lsp.util.buf_versions[bufnr] bufnr = resolve_bufnr(bufnr) - if log.debug() then - log.debug(self._log_prefix, 'client.request', self.id, method, params, handler, bufnr) - end + log.debug(self._log_prefix, 'client.request', self.id, method, params, handler, bufnr) local success, request_id = self.rpc.request(method, params, function(err, result) local context = { method = method, @@ -635,9 +630,7 @@ end --- @param code integer Error code --- @param err any Error arguments function Client:write_error(code, err) - if log.error() then - log.error(self._log_prefix, 'on_error', { code = lsp.client_errors[code], err = err }) - end + log.error(self._log_prefix, 'on_error', { code = lsp.client_errors[code], err = err }) err_message(self._log_prefix, ': Error ', lsp.client_errors[code], ': ', vim.inspect(err)) end diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index a045a6bad4..61e3448024 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -262,9 +262,7 @@ end function M.on_codelens(err, result, ctx, _) if err then active_refreshes[assert(ctx.bufnr)] = nil - if log.error() then - log.error('codelens', err) - end + log.error('codelens', err) return end diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 036b0e6151..aa812fa78c 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -35,7 +35,7 @@ local function severity_vim_to_lsp(severity) return severity end ----@param lines string[] +---@param lines string[]? ---@param lnum integer ---@param col integer ---@param offset_encoding string @@ -55,7 +55,7 @@ local function line_byte_from_position(lines, lnum, col, offset_encoding) end ---@param bufnr integer ----@return string[] +---@return string[]? local function get_buf_lines(bufnr) if vim.api.nvim_buf_is_loaded(bufnr) then return vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 26a71487e2..2fa539d963 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -413,9 +413,7 @@ M[ms.textDocument_hover] = M.hover ---(`textDocument/definition` can return `Location` or `Location[]` local function location_handler(_, result, ctx, config) if result == nil or vim.tbl_isempty(result) then - if log.info() then - log.info(ctx.method, 'No location found') - end + log.info(ctx.method, 'No location found') return nil end local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) @@ -649,13 +647,14 @@ end -- Add boilerplate error validation and logging for all of these. for k, fn in pairs(M) do M[k] = function(err, result, ctx, config) - local _ = log.trace() - and log.trace('default_handler', ctx.method, { + if log.trace() then + log.trace('default_handler', ctx.method, { err = err, result = result, ctx = vim.inspect(ctx), config = config, }) + end if err then -- LSP spec: diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua index 62138c0edf..49dc35fdf6 100644 --- a/runtime/lua/vim/lsp/inlay_hint.lua +++ b/runtime/lua/vim/lsp/inlay_hint.lua @@ -22,9 +22,7 @@ local augroup = api.nvim_create_augroup('vim_lsp_inlayhint', {}) ---@private function M.on_inlayhint(err, result, ctx, _) if err then - if log.error() then - log.error('inlayhint', err) - end + log.error('inlayhint', err) return end local bufnr = assert(ctx.bufnr) diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua index 00433474fe..a9d49bc8f4 100644 --- a/runtime/lua/vim/lsp/log.lua +++ b/runtime/lua/vim/lsp/log.lua @@ -12,130 +12,130 @@ log.levels = vim.deepcopy(vim.log.levels) -- Default log level is warn. local current_log_level = log.levels.WARN + local log_date_format = '%F %H:%M:%S' -local format_func = function(arg) + +local function format_func(arg) return vim.inspect(arg, { newline = '' }) end -do - local function notify(msg, level) - if vim.in_fast_event() then - vim.schedule(function() - vim.notify(msg, level) - end) - else +local function notify(msg, level) + if vim.in_fast_event() then + vim.schedule(function() vim.notify(msg, level) - end + end) + else + vim.notify(msg, level) end +end + +local logfilename = vim.fs.joinpath(vim.fn.stdpath('log'), 'lsp.log') + +-- TODO: Ideally the directory should be created in open_logfile(), right +-- before opening the log file, but open_logfile() can be called from libuv +-- callbacks, where using fn.mkdir() is not allowed. +vim.fn.mkdir(vim.fn.stdpath('log'), 'p') + +--- Returns the log filename. +---@return string log filename +function log.get_filename() + return logfilename +end + +--- @type file*?, string? +local logfile, openerr - local path_sep = vim.uv.os_uname().version:match('Windows') and '\\' or '/' - local function path_join(...) - return table.concat(vim.tbl_flatten({ ... }), path_sep) +--- Opens log file. Returns true if file is open, false on error +local function open_logfile() + -- Try to open file only once + if logfile then + return true + end + if openerr then + return false end - local logfilename = path_join(vim.fn.stdpath('log'), 'lsp.log') - -- TODO: Ideally the directory should be created in open_logfile(), right - -- before opening the log file, but open_logfile() can be called from libuv - -- callbacks, where using fn.mkdir() is not allowed. - vim.fn.mkdir(vim.fn.stdpath('log'), 'p') + logfile, openerr = io.open(logfilename, 'a+') + if not logfile then + local err_msg = string.format('Failed to open LSP client log file: %s', openerr) + notify(err_msg, vim.log.levels.ERROR) + return false + end - --- Returns the log filename. - ---@return string log filename - function log.get_filename() - return logfilename + local log_info = vim.uv.fs_stat(logfilename) + if log_info and log_info.size > 1e9 then + local warn_msg = string.format( + 'LSP client log is large (%d MB): %s', + log_info.size / (1000 * 1000), + logfilename + ) + notify(warn_msg) end - local logfile, openerr - --- Opens log file. Returns true if file is open, false on error - local function open_logfile() - -- Try to open file only once - if logfile then + -- Start message for logging + logfile:write(string.format('[START][%s] LSP logging initiated\n', os.date(log_date_format))) + return true +end + +for level, levelnr in pairs(log.levels) do + -- Also export the log level on the root object. + log[level] = levelnr +end + +vim.tbl_add_reverse_lookup(log.levels) + +--- @param level string +--- @param levelnr integer +--- @return fun(...:any): boolean? +local function create_logger(level, levelnr) + return function(...) + if levelnr < current_log_level then + return false + end + local argc = select('#', ...) + if argc == 0 then return true end - if openerr then + if not open_logfile() then return false end - - logfile, openerr = io.open(logfilename, 'a+') - if not logfile then - local err_msg = string.format('Failed to open LSP client log file: %s', openerr) - notify(err_msg, vim.log.levels.ERROR) - return false + local info = debug.getinfo(2, 'Sl') + local header = string.format( + '[%s][%s] ...%s:%s', + level, + os.date(log_date_format), + info.short_src:sub(-16), + info.currentline + ) + local parts = { header } + for i = 1, argc do + local arg = select(i, ...) + table.insert(parts, arg == nil and 'nil' or format_func(arg)) end + assert(logfile) + logfile:write(table.concat(parts, '\t'), '\n') + logfile:flush() + end +end - local log_info = vim.uv.fs_stat(logfilename) - if log_info and log_info.size > 1e9 then - local warn_msg = string.format( - 'LSP client log is large (%d MB): %s', - log_info.size / (1000 * 1000), - logfilename - ) - notify(warn_msg) - end +-- If called without arguments, it will check whether the log level is +-- greater than or equal to this one. When called with arguments, it will +-- log at that level (if applicable, it is checked either way). - -- Start message for logging - logfile:write(string.format('[START][%s] LSP logging initiated\n', os.date(log_date_format))) - return true - end +--- @nodoc +log.debug = create_logger('DEBUG', vim.log.levels.DEBUG) - for level, levelnr in pairs(log.levels) do - -- Also export the log level on the root object. - log[level] = levelnr - -- FIXME: DOC - -- Should be exposed in the vim docs. - -- - -- Set the lowercase name as the main use function. - -- If called without arguments, it will check whether the log level is - -- greater than or equal to this one. When called with arguments, it will - -- log at that level (if applicable, it is checked either way). - -- - -- Recommended usage: - -- ``` - -- if log.warn() then - -- log.warn("123") - -- end - -- ``` - -- - -- This way you can avoid string allocations if the log level isn't high enough. - if level ~= 'OFF' then - log[level:lower()] = function(...) - local argc = select('#', ...) - if levelnr < current_log_level then - return false - end - if argc == 0 then - return true - end - if not open_logfile() then - return false - end - local info = debug.getinfo(2, 'Sl') - local header = string.format( - '[%s][%s] ...%s:%s', - level, - os.date(log_date_format), - string.sub(info.short_src, #info.short_src - 15), - info.currentline - ) - local parts = { header } - for i = 1, argc do - local arg = select(i, ...) - if arg == nil then - table.insert(parts, 'nil') - else - table.insert(parts, format_func(arg)) - end - end - logfile:write(table.concat(parts, '\t'), '\n') - logfile:flush() - end - end - end -end +--- @nodoc +log.error = create_logger('ERROR', vim.log.levels.ERROR) --- This is put here on purpose after the loop above so that it doesn't --- interfere with iterating the levels -vim.tbl_add_reverse_lookup(log.levels) +--- @nodoc +log.info = create_logger('INFO', vim.log.levels.INFO) + +--- @nodoc +log.trace = create_logger('TRACE', vim.log.levels.TRACE) + +--- @nodoc +log.warn = create_logger('WARN', vim.log.levels.WARN) --- Sets the current log level. ---@param level (string|integer) One of `vim.lsp.log.levels` diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 660b126ce4..1aacf63392 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -26,24 +26,6 @@ local function format_message_with_content_length(message) }) end -local function log_error(...) - if log.error() then - log.error(...) - end -end - -local function log_info(...) - if log.info() then - log.info(...) - end -end - -local function log_debug(...) - if log.debug() then - log.debug(...) - end -end - ---@class vim.lsp.rpc.Headers: {string: any} ---@field content_length integer @@ -65,7 +47,7 @@ local function parse_headers(header) key = key:lower():gsub('%-', '_') --- @type string headers[key] = value else - log_error('invalid header line %q', line) + log.error('invalid header line %q', line) error(string.format('invalid header line %q', line)) end end @@ -224,7 +206,7 @@ local default_dispatchers = { ---@param method string The invoked LSP method ---@param params table Parameters for the invoked LSP method notification = function(method, params) - log_debug('notification', method, params) + log.debug('notification', method, params) end, --- Default dispatcher for requests sent to an LSP server. @@ -234,7 +216,7 @@ local default_dispatchers = { ---@return any result (always nil for the default dispatchers) ---@return lsp.ResponseError error `vim.lsp.protocol.ErrorCodes.MethodNotFound` server_request = function(method, params) - log_debug('server_request', method, params) + log.debug('server_request', method, params) return nil, M.rpc_response_error(protocol.ErrorCodes.MethodNotFound) end, @@ -243,7 +225,7 @@ local default_dispatchers = { ---@param code integer Exit code ---@param signal integer Number describing the signal used to terminate (if any) on_exit = function(code, signal) - log_info('client_exit', { code = code, signal = signal }) + log.info('client_exit', { code = code, signal = signal }) end, --- Default dispatcher for client errors. @@ -251,7 +233,7 @@ local default_dispatchers = { ---@param code integer Error code ---@param err any Details about the error on_error = function(code, err) - log_error('client_error:', M.client_errors[code], err) + log.error('client_error:', M.client_errors[code], err) end, } @@ -297,7 +279,7 @@ local Client = {} ---@private function Client:encode_and_send(payload) - log_debug('rpc.send', payload) + log.debug('rpc.send', payload) if self.transport.is_closing() then return false end @@ -419,7 +401,7 @@ function Client:handle_body(body) self:on_error(M.client_errors.INVALID_SERVER_JSON, decoded) return end - log_debug('rpc.receive', decoded) + log.debug('rpc.receive', decoded) if type(decoded.method) == 'string' and decoded.id then local err --- @type lsp.ResponseError|nil @@ -434,7 +416,7 @@ function Client:handle_body(body) decoded.method, decoded.params ) - log_debug( + log.debug( 'server_request: callback result', { status = status, result = result, err = err } ) @@ -490,7 +472,7 @@ function Client:handle_body(body) if decoded.error then local mute_error = false if decoded.error.code == protocol.ErrorCodes.RequestCancelled then - log_debug('Received cancellation ack', decoded) + log.debug('Received cancellation ack', decoded) mute_error = true end @@ -526,7 +508,7 @@ function Client:handle_body(body) ) else self:on_error(M.client_errors.NO_RESULT_CALLBACK_FOUND, decoded) - log_error('No callback found for server response id ' .. result_id) + log.error('No callback found for server response id ' .. result_id) end elseif type(decoded.method) == 'string' then -- Notification @@ -773,7 +755,7 @@ end --- - `is_closing()` returns a boolean indicating if the RPC is closing. --- - `terminate()` terminates the RPC client. function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) - log_info('Starting RPC client', { cmd = cmd, args = cmd_args, extra = extra_spawn_params }) + log.info('Starting RPC client', { cmd = cmd, args = cmd_args, extra = extra_spawn_params }) validate({ cmd = { cmd, 's' }, @@ -813,7 +795,7 @@ function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) local stderr_handler = function(_, chunk) if chunk then - log_error('rpc', cmd, 'stderr', chunk) + log.error('rpc', cmd, 'stderr', chunk) end end -- cgit From 800134ea5ec60338a40280c8536db6a6a4a10249 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Thu, 25 Jan 2024 13:27:48 -0500 Subject: refactor(treesitter): typing for Query, TSQuery, and TSQueryInfo - `TSQuery`: userdata object for parsed query. - `vim.treesitter.Query`: renamed from `Query`. - Add a new field `lang`. - `TSQueryInfo`: - Move to `vim/treesitter/_meta.lua`, because C code owns it. - Correct typing for `patterns`, should be a map from `integer` (pattern_id) to `(integer|string)[][]` (list of predicates or directives). - `vim.treesitter.QueryInfo` is added. - This currently has the same structure as `TSQueryInfo` (exported from C code). - Document the fields (see `TSQuery:inspect`). - Add typing for `vim._ts_parse_query()`. --- runtime/lua/vim/treesitter/_meta.lua | 23 +++++++--- runtime/lua/vim/treesitter/highlighter.lua | 2 +- runtime/lua/vim/treesitter/query.lua | 68 +++++++++++++++++++++--------- 3 files changed, 67 insertions(+), 26 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/_meta.lua b/runtime/lua/vim/treesitter/_meta.lua index 80c998b555..6a714de052 100644 --- a/runtime/lua/vim/treesitter/_meta.lua +++ b/runtime/lua/vim/treesitter/_meta.lua @@ -1,4 +1,5 @@ ---@meta +error('Cannot require a meta file') ---@class TSNode: userdata ---@field id fun(self: TSNode): string @@ -33,7 +34,7 @@ ---@field byte_length fun(self: TSNode): integer local TSNode = {} ----@param query userdata +---@param query TSQuery ---@param captures true ---@param start? integer ---@param end_? integer @@ -41,17 +42,17 @@ local TSNode = {} ---@return fun(): integer, TSNode, any function TSNode:_rawquery(query, captures, start, end_, opts) end ----@param query userdata +---@param query TSQuery ---@param captures false ---@param start? integer ---@param end_? integer ---@param opts? table ----@return fun(): string, any +---@return fun(): integer, any function TSNode:_rawquery(query, captures, start, end_, opts) end ---@alias TSLoggerCallback fun(logtype: 'parse'|'lex', msg: string) ----@class TSParser +---@class TSParser: userdata ---@field parse fun(self: TSParser, tree: TSTree?, source: integer|string, include_bytes: true): TSTree, Range6[] ---@field parse fun(self: TSParser, tree: TSTree?, source: integer|string, include_bytes: false|nil): TSTree, Range4[] ---@field reset fun(self: TSParser) @@ -62,19 +63,31 @@ function TSNode:_rawquery(query, captures, start, end_, opts) end ---@field _set_logger fun(self: TSParser, lex: boolean, parse: boolean, cb: TSLoggerCallback) ---@field _logger fun(self: TSParser): TSLoggerCallback ----@class TSTree +---@class TSTree: userdata ---@field root fun(self: TSTree): TSNode ---@field edit fun(self: TSTree, _: integer, _: integer, _: integer, _: integer, _: integer, _: integer, _: integer, _: integer, _:integer) ---@field copy fun(self: TSTree): TSTree ---@field included_ranges fun(self: TSTree, include_bytes: true): Range6[] ---@field included_ranges fun(self: TSTree, include_bytes: false): Range4[] +---@class TSQuery: userdata +---@field inspect fun(self: TSQuery): TSQueryInfo + +---@class (exact) TSQueryInfo +---@field captures string[] +---@field patterns table + ---@return integer vim._ts_get_language_version = function() end ---@return integer vim._ts_get_minimum_language_version = function() end +---@param lang string Language to use for the query +---@param query string Query string in s-expr syntax +---@return TSQuery +vim._ts_parse_query = function(lang, query) end + ---@param lang string ---@return TSParser vim._create_ts_parser = function(lang) end diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 84d40322fe..08c4c2a832 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -7,7 +7,7 @@ local ns = api.nvim_create_namespace('treesitter/highlighter') ---@alias vim.treesitter.highlighter.Iter fun(end_line: integer|nil): integer, TSNode, TSMetadata ---@class vim.treesitter.highlighter.Query ----@field private _query Query? +---@field private _query vim.treesitter.query.Query? ---@field private lang string ---@field private hl_cache table local TSHighlighterQuery = {} diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 63d4a9382a..7631c6c4a2 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -1,18 +1,48 @@ local api = vim.api local language = require('vim.treesitter.language') ----@class Query ----@field captures string[] List of captures used in query ----@field info TSQueryInfo Contains used queries, predicates, directives ----@field query userdata Parsed query +local M = {} + +---Parsed query, see |vim.treesitter.query.parse()| +--- +---@class vim.treesitter.Query +---@field lang string name of the language for this parser +---@field captures string[] list of (unique) capture names defined in query +---@field info vim.treesitter.QueryInfo contains information used in the query (e.g. captures, predicates, directives) +---@field query TSQuery userdata query object local Query = {} Query.__index = Query ----@class TSQueryInfo ----@field captures table ----@field patterns table +---@package +---@see vim.treesitter.query.parse +---@param lang string +---@param ts_query TSQuery +---@return vim.treesitter.Query +function Query.new(lang, ts_query) + local self = setmetatable({}, Query) + local query_info = ts_query:inspect() ---@type TSQueryInfo + self.query = ts_query + self.lang = lang + self.info = { + captures = query_info.captures, + patterns = query_info.patterns, + } + self.captures = self.info.captures + return self +end -local M = {} +---Information for Query, see |vim.treesitter.query.parse()| +---@class vim.treesitter.QueryInfo +--- +---List of (unique) capture names defined in query. +---@field captures string[] +--- +---Contains information about predicates and directives. +---Key is pattern id, and value is list of predicates or directives defined in the pattern. +---A predicate or directive is a list of (integer|string); integer represents `capture_id`, and +---string represents (literal) arguments to predicate/directive. See |treesitter-predicates| +---and |treesitter-directives| for more details. +---@field patterns table ---@param files string[] ---@return string[] @@ -162,7 +192,7 @@ local function read_query_files(filenames) end -- The explicitly set queries from |vim.treesitter.query.set()| ----@type table> +---@type table> local explicit_queries = setmetatable({}, { __index = function(t, k) local lang_queries = {} @@ -201,7 +231,7 @@ end ---@param lang string Language to use for the query ---@param query_name string Name of the query (e.g. "highlights") --- ----@return Query|nil Parsed query +---@return vim.treesitter.Query|nil -- Parsed query. `nil` if no query files are found. M.get = vim.func._memoize('concat-2', function(lang, query_name) if explicit_queries[lang][query_name] then return explicit_queries[lang][query_name] @@ -228,26 +258,24 @@ end --- --- Returns a `Query` (see |lua-treesitter-query|) object which can be used to --- search nodes in the syntax tree for the patterns defined in {query} ---- using `iter_*` methods below. +--- using the `iter_captures` and `iter_matches` methods. --- --- Exposes `info` and `captures` with additional context about {query}. ---- - `captures` contains the list of unique capture names defined in ---- {query}. ---- -` info.captures` also points to `captures`. +--- - `captures` contains the list of unique capture names defined in {query}. +--- - `info.captures` also points to `captures`. --- - `info.patterns` contains information about predicates. --- ---@param lang string Language to use for the query ---@param query string Query in s-expr syntax --- ----@return Query Parsed query +---@return vim.treesitter.Query Parsed query +--- +---@see |vim.treesitter.query.get()| M.parse = vim.func._memoize('concat-2', function(lang, query) language.add(lang) - local self = setmetatable({}, Query) - self.query = vim._ts_parse_query(lang, query) - self.info = self.query:inspect() - self.captures = self.info.captures - return self + local ts_query = vim._ts_parse_query(lang, query) + return Query.new(lang, ts_query) end) ---@deprecated -- cgit From d0e9e36a7841c28f82e5c7ae2bde1fa21319f2ac Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Fri, 2 Feb 2024 01:51:35 -0500 Subject: refactor(treesitter): {start,stop} are optional in Query:iter_* methods Document that the `start` and `stop` parameters in `Query:iter_captures()` and `Query:iter_matches()` are optional. The tree-sitter lib has been bumped up to 0.20.9, so we also no longer need "Requires treesitter >= 0.20.9". --- runtime/lua/vim/treesitter/query.lua | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 7631c6c4a2..cd65c0d7f6 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -672,14 +672,16 @@ end --- Returns the start and stop value if set else the node's range. -- When the node's range is used, the stop is incremented by 1 -- to make the search inclusive. ----@param start integer ----@param stop integer +---@param start integer|nil +---@param stop integer|nil ---@param node TSNode ---@return integer, integer local function value_or_node_range(start, stop, node) - if start == nil and stop == nil then - local node_start, _, node_stop, _ = node:range() - return node_start, node_stop + 1 -- Make stop inclusive + if start == nil then + start = node:start() + end + if stop == nil then + stop = node:end_() + 1 -- Make stop inclusive end return start, stop @@ -710,8 +712,8 @@ end --- ---@param node TSNode under which the search will occur ---@param source (integer|string) Source buffer or string to extract text from ----@param start integer Starting line for the search ----@param stop integer Stopping line for the search (end-exclusive) +---@param start? integer Starting line for the search. Defaults to `node:start()`. +---@param stop? integer Stopping line for the search (end-exclusive). Defaults to `node:end_()`. --- ---@return (fun(end_line: integer|nil): integer, TSNode, TSMetadata): --- capture id, capture node, metadata @@ -769,12 +771,11 @@ end --- ---@param node TSNode under which the search will occur ---@param source (integer|string) Source buffer or string to search ----@param start integer Starting line for the search ----@param stop integer Stopping line for the search (end-exclusive) ----@param opts table|nil Options: +---@param start? integer Starting line for the search. Defaults to `node:start()`. +---@param stop? integer Stopping line for the search (end-exclusive). Defaults to `node:end_()`. +---@param opts? table Optional keyword arguments: --- - max_start_depth (integer) if non-zero, sets the maximum start depth --- for each match. This is used to prevent traversing too deep into a tree. ---- Requires treesitter >= 0.20.9. --- ---@return (fun(): integer, table, table): pattern id, match, metadata function Query:iter_matches(node, source, start, stop, opts) -- cgit From 451bc50d40ee43a40285d16039deb83c9bf05ff6 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 8 Feb 2024 12:11:47 +0000 Subject: feat(lsp): deprecate severity_limit Problem: `vim.lsp.diagnostic.on_diagnostic` accepts an undocumented severity_limit option which is widely used. Solution: Deprecate it in favour of `{min = severity}` used in `vim.diagnostic`. Since this is undocumented, the schedule for removal is accelerated to 0.11. --- runtime/lua/vim/lsp/diagnostic.lua | 52 ++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 28 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index aa812fa78c..3a4064a1e4 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -221,6 +221,13 @@ function M.get_namespace(client_id, is_pull) end end +local function convert_severity(opt) + if type(opt) == 'table' and not opt.severity and opt.severity_limit then + vim.deprecate('severity_limit', '{min = severity} See vim.diagnostic.severity', '0.11') + opt.severity = { min = severity_lsp_to_vim(opt.severity_limit) } + end +end + --- |lsp-handler| for the method "textDocument/publishDiagnostics" --- --- See |vim.diagnostic.config()| for configuration options. Handler-specific @@ -267,13 +274,8 @@ function M.on_publish_diagnostics(_, result, ctx, config) if config then for _, opt in pairs(config) do - if type(opt) == 'table' then - if not opt.severity and opt.severity_limit then - opt.severity = { min = severity_lsp_to_vim(opt.severity_limit) } - end - end + convert_severity(opt) end - -- Persist configuration to ensure buffer reloads use the same -- configuration. To make lsp.with configuration work (See :help -- lsp-handler-configuration) @@ -308,11 +310,14 @@ end --- ) --- ``` --- +---@param result lsp.DocumentDiagnosticReport ---@param ctx lsp.HandlerContext ---@param config table Configuration table (see |vim.diagnostic.config()|). function M.on_diagnostic(_, result, ctx, config) local client_id = ctx.client_id - local uri = ctx.params.textDocument.uri + --- @type lsp.DocumentDiagnosticParams + local params = ctx.params + local uri = params.textDocument.uri local fname = vim.uri_to_fname(uri) if result == nil then @@ -339,11 +344,8 @@ function M.on_diagnostic(_, result, ctx, config) if config then for _, opt in pairs(config) do - if type(opt) == 'table' and not opt.severity and opt.severity_limit then - opt.severity = { min = severity_lsp_to_vim(opt.severity_limit) } - end + convert_severity(opt) end - -- Persist configuration to ensure buffer reloads use the same -- configuration. To make lsp.with configuration work (See :help -- lsp-handler-configuration) @@ -381,34 +383,28 @@ end --- ---@param bufnr integer|nil The buffer number ---@param line_nr integer|nil The line number ----@param opts table|nil Configuration keys ---- - severity: (DiagnosticSeverity, default nil) ---- - Only return diagnostics with this severity. Overrides severity_limit ---- - severity_limit: (DiagnosticSeverity, default nil) ---- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid. +---@param opts {severity?:lsp.DiagnosticSeverity}? +--- - severity: (lsp.DiagnosticSeverity) +--- - Only return diagnostics with this severity. ---@param client_id integer|nil the client id ---@return table Table with map of line number to list of diagnostics. --- Structured: { [1] = {...}, [5] = {.... } } ---@private function M.get_line_diagnostics(bufnr, line_nr, opts, client_id) - opts = opts or {} - if opts.severity then - opts.severity = severity_lsp_to_vim(opts.severity) - elseif opts.severity_limit then - opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) } - end + convert_severity(opts) + local diag_opts = {} --- @type vim.diagnostic.GetOpts - if client_id then - opts.namespace = M.get_namespace(client_id, false) + if opts and opts.severity then + diag_opts.severity = severity_lsp_to_vim(opts.severity) end - if not line_nr then - line_nr = vim.api.nvim_win_get_cursor(0)[1] - 1 + if client_id then + diag_opts.namespace = M.get_namespace(client_id, false) end - opts.lnum = line_nr + diag_opts.lnum = line_nr or (api.nvim_win_get_cursor(0)[1] - 1) - return diagnostic_vim_to_lsp(vim.diagnostic.get(bufnr, opts)) + return diagnostic_vim_to_lsp(vim.diagnostic.get(bufnr, diag_opts)) end --- Clear diagnostics from pull based clients -- cgit From f0e61e6d92b5ce115388f8a03f8d34f00a3dea92 Mon Sep 17 00:00:00 2001 From: Tomasz N Date: Thu, 8 Feb 2024 22:06:54 +0100 Subject: fix(lsp): rename fails on missing parent directory #27291 Problem: If a rename results in a path that has missing parent directory(s), it will fail. Solution: Do a recursive mkdir before attempting the rename. --- runtime/lua/vim/lsp/util.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index b5e15e135c..86bef1ac8a 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -693,6 +693,9 @@ function M.rename(old_fname, new_fname, opts) end) end + local newdir = assert(vim.fs.dirname(new_fname)) + vim.fn.mkdir(newdir, 'p') + local ok, err = os.rename(old_fname, new_fname) assert(ok, err) -- cgit From 0fe86f7e240368c00ffa06516cd34850b92e00d3 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Sun, 28 Jan 2024 22:21:37 -0800 Subject: feat(lsp): add opts paramater to vim.lsp.codelens.refresh --- runtime/lua/vim/lsp/codelens.lua | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index 61e3448024..ab49e03c52 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -48,6 +48,7 @@ local function execute_lens(lens, bufnr, client_id) local client = vim.lsp.get_client_by_id(client_id) assert(client, 'Client is required to execute lens, client_id=' .. client_id) + ---@diagnostic disable-next-line: invisible client:_exec_cmd(lens.command, { bufnr = bufnr }, function(...) vim.lsp.handlers[ms.workspace_executeCommand](...) M.refresh() @@ -111,7 +112,7 @@ end --- Clear the lenses --- ---@param client_id integer|nil filter by client_id. All clients if nil ----@param bufnr integer|nil filter by buffer. All buffers if nil +---@param bufnr integer|nil filter by buffer. All buffers if nil, 0 for current buffer function M.clear(client_id, bufnr) bufnr = bufnr and resolve_bufnr(bufnr) local buffers = bufnr and { bufnr } @@ -277,25 +278,36 @@ function M.on_codelens(err, result, ctx, _) end) end ---- Refresh the codelens for the current buffer +--- @class vim.lsp.codelens.RefreshOptions +--- @field bufnr integer? filter by buffer. All buffers if nil, 0 for current buffer + +--- Refresh the lenses. --- --- It is recommended to trigger this using an autocmd or via keymap. --- --- Example: --- --- ```vim ---- autocmd BufEnter,CursorHold,InsertLeave lua vim.lsp.codelens.refresh() +--- autocmd BufEnter,CursorHold,InsertLeave lua vim.lsp.codelens.refresh({ bufnr = 0 }) --- ``` -function M.refresh() +--- +--- @param opts? vim.lsp.codelens.RefreshOptions Table with the following fields: +--- - `bufnr` (integer|nil): filter by buffer. All buffers if nil, 0 for current buffer +function M.refresh(opts) + opts = opts or {} + local bufnr = opts.bufnr and resolve_bufnr(opts.bufnr) + local buffers = bufnr and { bufnr } + or vim.tbl_filter(api.nvim_buf_is_loaded, api.nvim_list_bufs()) local params = { textDocument = util.make_text_document_params(), } - local bufnr = api.nvim_get_current_buf() - if active_refreshes[bufnr] then - return + + for _, buf in ipairs(buffers) do + if not active_refreshes[buf] then + active_refreshes[buf] = true + vim.lsp.buf_request(buf, ms.textDocument_codeLens, params, M.on_codelens) + end end - active_refreshes[bufnr] = true - vim.lsp.buf_request(0, ms.textDocument_codeLens, params, M.on_codelens) end return M -- cgit From 44ec4b5b18d1ba856dc3305d8dfb0e8d9507dd50 Mon Sep 17 00:00:00 2001 From: Will Hopkins Date: Fri, 9 Feb 2024 08:17:10 -0800 Subject: refactor: rename FloatConfig to WinConfig #27397 `FloatConfig` is no longer used only for floats, so the name is counterintuitive. Followup to #25550 --- runtime/lua/vim/_meta/api.lua | 4 +-- runtime/lua/vim/_meta/api_keysets.lua | 48 +++++++++++++++++------------------ 2 files changed, 26 insertions(+), 26 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 8b29727196..f46ab8023f 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1535,7 +1535,7 @@ function vim.api.nvim_open_term(buffer, opts) end --- --- @param buffer integer Buffer to display, or 0 for current buffer --- @param enter boolean Enter the window (make it the current window) ---- @param config vim.api.keyset.float_config Map defining the window configuration. Keys: +--- @param config vim.api.keyset.win_config Map defining the window configuration. Keys: --- • relative: Sets the window layout to "floating", placed at --- (row,col) coordinates relative to: --- • "editor" The global editor grid @@ -2093,7 +2093,7 @@ function vim.api.nvim_win_set_buf(window, buffer) end --- changed. `row`/`col` and `relative` must be reconfigured together. --- --- @param window integer Window handle, or 0 for current window ---- @param config vim.api.keyset.float_config Map defining the window configuration, see `nvim_open_win()` +--- @param config vim.api.keyset.win_config Map defining the window configuration, see `nvim_open_win()` function vim.api.nvim_win_set_config(window, config) end --- Sets the (1,0)-indexed cursor position in the window. `api-indexing` This diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index 1b6c6811a2..0442a89e3f 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -111,30 +111,6 @@ error('Cannot require a meta file') --- @class vim.api.keyset.exec_opts --- @field output? boolean ---- @class vim.api.keyset.float_config ---- @field row? number ---- @field col? number ---- @field width? integer ---- @field height? integer ---- @field anchor? string ---- @field relative? string ---- @field split? string ---- @field win? integer ---- @field bufpos? any[] ---- @field external? boolean ---- @field focusable? boolean ---- @field vertical? boolean ---- @field zindex? integer ---- @field border? any ---- @field title? any ---- @field title_pos? string ---- @field footer? any ---- @field footer_pos? string ---- @field style? string ---- @field noautocmd? boolean ---- @field fixed? boolean ---- @field hide? boolean - --- @class vim.api.keyset.get_autocmds --- @field event? any --- @field group? any @@ -292,6 +268,30 @@ error('Cannot require a meta file') --- @field range? any --- @field register? boolean +--- @class vim.api.keyset.win_config +--- @field row? number +--- @field col? number +--- @field width? integer +--- @field height? integer +--- @field anchor? string +--- @field relative? string +--- @field split? string +--- @field win? integer +--- @field bufpos? any[] +--- @field external? boolean +--- @field focusable? boolean +--- @field vertical? boolean +--- @field zindex? integer +--- @field border? any +--- @field title? any +--- @field title_pos? string +--- @field footer? any +--- @field footer_pos? string +--- @field style? string +--- @field noautocmd? boolean +--- @field fixed? boolean +--- @field hide? boolean + --- @class vim.api.keyset.win_text_height --- @field start_row? integer --- @field end_row? integer -- cgit From 170c890dca8f160bdcd41e4fdc6bf15ee0bdba49 Mon Sep 17 00:00:00 2001 From: Trevor Arjeski Date: Sun, 11 Feb 2024 02:39:39 +0300 Subject: feat(shortmess): "q" flag fully hides recording message (#27415) When "q" is set in 'shortmess' it now fully hides the "recording @a" message when you are recording a macro instead of just shortening to "recording". This removes duplication when using reg_recording() in the statusline. Related #19193 --- runtime/lua/vim/_meta/options.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 83da61cc2b..835bd95a3a 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -5797,7 +5797,7 @@ vim.bo.sw = vim.bo.shiftwidth --- match", "Pattern not found", "Back at original", etc. --- C don't give messages while scanning for ins-completion *shm-C* --- items, for instance "scanning tags" ---- q use "recording" instead of "recording @a" *shm-q* +--- q do not show "recording @a" when recording a macro *shm-q* --- F don't give the file info when editing a file, like *shm-F* --- `:silent` was used for the command --- S do not show search count message when searching, e.g. *shm-S* -- cgit From c73d67d283c296bdb7a44a0283346e7b61d837f0 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Sat, 10 Feb 2024 14:03:44 -0800 Subject: refactor(lsp): add type annotations --- runtime/lua/vim/lsp/_changetracking.lua | 2 +- runtime/lua/vim/lsp/_dynamic.lua | 2 +- runtime/lua/vim/lsp/client.lua | 5 +++-- runtime/lua/vim/lsp/diagnostic.lua | 9 +++++---- runtime/lua/vim/lsp/health.lua | 2 +- runtime/lua/vim/lsp/rpc.lua | 2 +- runtime/lua/vim/lsp/sync.lua | 13 ++++++------- 7 files changed, 18 insertions(+), 17 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/_changetracking.lua b/runtime/lua/vim/lsp/_changetracking.lua index 67c74f069d..8b624cd5ea 100644 --- a/runtime/lua/vim/lsp/_changetracking.lua +++ b/runtime/lua/vim/lsp/_changetracking.lua @@ -64,7 +64,7 @@ local state_by_group = setmetatable({}, { ---@param client lsp.Client ---@return vim.lsp.CTGroup local function get_group(client) - local allow_inc_sync = vim.F.if_nil(client.config.flags.allow_incremental_sync, true) + local allow_inc_sync = vim.F.if_nil(client.config.flags.allow_incremental_sync, true) --- @type boolean local change_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'change') local sync_kind = change_capability or protocol.TextDocumentSyncKind.None if not allow_inc_sync and change_capability == protocol.TextDocumentSyncKind.Incremental then diff --git a/runtime/lua/vim/lsp/_dynamic.lua b/runtime/lua/vim/lsp/_dynamic.lua index 8b8f3bdc38..b6c335bb13 100644 --- a/runtime/lua/vim/lsp/_dynamic.lua +++ b/runtime/lua/vim/lsp/_dynamic.lua @@ -24,7 +24,7 @@ function M:supports_registration(method) end --- @param registrations lsp.Registration[] ---- @private +--- @package function M:register(registrations) -- remove duplicates self:unregister(registrations) diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index 0bcbb35be6..7bf83f4d2c 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -630,8 +630,9 @@ end --- @param code integer Error code --- @param err any Error arguments function Client:write_error(code, err) - log.error(self._log_prefix, 'on_error', { code = lsp.client_errors[code], err = err }) - err_message(self._log_prefix, ': Error ', lsp.client_errors[code], ': ', vim.inspect(err)) + local client_error = lsp.client_errors[code] --- @type string|integer + log.error(self._log_prefix, 'on_error', { code = client_error, err = err }) + err_message(self._log_prefix, ': Error ', client_error, ': ', vim.inspect(err)) end --- @param method string diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 3a4064a1e4..5fdadd1771 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -22,7 +22,7 @@ end ---@param severity lsp.DiagnosticSeverity local function severity_lsp_to_vim(severity) if type(severity) == 'string' then - severity = protocol.DiagnosticSeverity[severity] + severity = protocol.DiagnosticSeverity[severity] --- @type integer end return severity end @@ -48,7 +48,7 @@ local function line_byte_from_position(lines, lnum, col, offset_encoding) local line = lines[lnum + 1] local ok, result = pcall(vim.str_byteindex, line, col, offset_encoding == 'utf-16') if ok then - return result + return result --- @type integer end return col @@ -362,7 +362,7 @@ end --- implementation so it's simply marked @private rather than @deprecated. --- ---@param client_id integer ----@param buffer_client_map table map of buffers to active clients +---@param buffer_client_map table> map of buffers to active clients ---@private function M.reset(client_id, buffer_client_map) buffer_client_map = vim.deepcopy(buffer_client_map) @@ -462,7 +462,8 @@ function M._enable(bufnr) return end if bufstates[bufnr] and bufstates[bufnr].enabled then - _refresh(bufnr, { only_visible = true, client_id = opts.data.client_id }) + local client_id = opts.data.client_id --- @type integer? + _refresh(bufnr, { only_visible = true, client_id = client_id }) end end, group = augroup, diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua index 9c989e5246..d770735895 100644 --- a/runtime/lua/vim/lsp/health.lua +++ b/runtime/lua/vim/lsp/health.lua @@ -7,7 +7,7 @@ function M.check() local log = vim.lsp.log local current_log_level = log.get_level() - local log_level_string = log.levels[current_log_level] + local log_level_string = log.levels[current_log_level] ---@type string report_info(string.format('LSP log level : %s', log_level_string)) if current_log_level < log.levels.WARN then diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 1aacf63392..23f70826e5 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -498,7 +498,7 @@ function Client:handle_body(body) if decoded.error then decoded.error = setmetatable(decoded.error, { __tostring = M.format_rpc_error, - }) + }) --- @type table end self:try_call( M.client_errors.SERVER_RESULT_CALLBACK_ERROR, diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua index 7ebe2dbb88..7eed542667 100644 --- a/runtime/lua/vim/lsp/sync.lua +++ b/runtime/lua/vim/lsp/sync.lua @@ -58,8 +58,7 @@ local function byte_to_utf(line, byte, offset_encoding) -- convert to 0 based indexing for str_utfindex byte = byte - 1 - local utf_idx --- @type integer - local _ + local utf_idx, _ --- @type integer, integer -- Convert the byte range to utf-{8,16,32} and convert 1-based (lua) indexing to 0-based if offset_encoding == 'utf-16' then _, utf_idx = str_utfindex(line, byte) @@ -77,8 +76,7 @@ end ---@param offset_encoding string ---@return integer local function compute_line_length(line, offset_encoding) - local length --- @type integer - local _ + local length, _ --- @type integer, integer if offset_encoding == 'utf-16' then _, length = str_utfindex(line) elseif offset_encoding == 'utf-32' then @@ -202,9 +200,10 @@ end --- prev_end_range is the text range sent to the server representing the changed region. --- curr_end_range is the text that should be collected and sent to the server. -- ----@param prev_lines table list of lines ----@param curr_lines table list of lines ---@param start_range table +---@param prev_lines string[] list of lines +---@param curr_lines string[] list of lines +---@param firstline integer ---@param lastline integer ---@param new_lastline integer ---@param offset_encoding string @@ -253,7 +252,7 @@ local function compute_end_range( -- Editing the same line -- If the byte offset is zero, that means there is a difference on the last byte (not newline) if prev_line_idx == curr_line_idx then - local max_length + local max_length --- @type integer if start_line_idx == prev_line_idx then -- Search until beginning of difference max_length = min( -- cgit From 5a6868c888a9ef5bd22e004e7cb116e4578ccf32 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Sat, 10 Feb 2024 14:04:05 -0800 Subject: refactor(lsp): add shared diagnostic handler --- runtime/lua/vim/lsp/diagnostic.lua | 103 ++++++++++++++----------------------- 1 file changed, 39 insertions(+), 64 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 5fdadd1771..33051ab61c 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -228,6 +228,40 @@ local function convert_severity(opt) end end +--- @param uri string +--- @param client_id? integer +--- @param diagnostics vim.Diagnostic[] +--- @param is_pull boolean +--- @param config? vim.diagnostic.Opts +local function handle_diagnostics(uri, client_id, diagnostics, is_pull, config) + local fname = vim.uri_to_fname(uri) + + if #diagnostics == 0 and vim.fn.bufexists(fname) == 0 then + return + end + + local bufnr = vim.fn.bufadd(fname) + if not bufnr then + return + end + + client_id = get_client_id(client_id) + local namespace = M.get_namespace(client_id, is_pull) + + if config then + --- @cast config table + for _, opt in pairs(config) do + convert_severity(opt) + end + -- Persist configuration to ensure buffer reloads use the same + -- configuration. To make lsp.with configuration work (See :help + -- lsp-handler-configuration) + vim.diagnostic.config(config, namespace) + end + + vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)) +end + --- |lsp-handler| for the method "textDocument/publishDiagnostics" --- --- See |vim.diagnostic.config()| for configuration options. Handler-specific @@ -253,36 +287,11 @@ end --- ) --- ``` --- +---@param result lsp.PublishDiagnosticsParams ---@param ctx lsp.HandlerContext ----@param config table Configuration table (see |vim.diagnostic.config()|). +---@param config? vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|). function M.on_publish_diagnostics(_, result, ctx, config) - local client_id = ctx.client_id - local uri = result.uri - local fname = vim.uri_to_fname(uri) - local diagnostics = result.diagnostics - if #diagnostics == 0 and vim.fn.bufexists(fname) == 0 then - return - end - local bufnr = vim.fn.bufadd(fname) - - if not bufnr then - return - end - - client_id = get_client_id(client_id) - local namespace = M.get_namespace(client_id, false) - - if config then - for _, opt in pairs(config) do - convert_severity(opt) - end - -- Persist configuration to ensure buffer reloads use the same - -- configuration. To make lsp.with configuration work (See :help - -- lsp-handler-configuration) - vim.diagnostic.config(config, namespace) - end - - vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)) + handle_diagnostics(result.uri, ctx.client_id, result.diagnostics, false, config) end --- |lsp-handler| for the method "textDocument/diagnostic" @@ -314,45 +323,11 @@ end ---@param ctx lsp.HandlerContext ---@param config table Configuration table (see |vim.diagnostic.config()|). function M.on_diagnostic(_, result, ctx, config) - local client_id = ctx.client_id - --- @type lsp.DocumentDiagnosticParams - local params = ctx.params - local uri = params.textDocument.uri - local fname = vim.uri_to_fname(uri) - - if result == nil then - return - end - - if result.kind == 'unchanged' then + if result == nil or result.kind == 'unchanged' then return end - local diagnostics = result.items - if #diagnostics == 0 and vim.fn.bufexists(fname) == 0 then - return - end - local bufnr = vim.fn.bufadd(fname) - - if not bufnr then - return - end - - client_id = get_client_id(client_id) - - local namespace = M.get_namespace(client_id, true) - - if config then - for _, opt in pairs(config) do - convert_severity(opt) - end - -- Persist configuration to ensure buffer reloads use the same - -- configuration. To make lsp.with configuration work (See :help - -- lsp-handler-configuration) - vim.diagnostic.config(config, namespace) - end - - vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)) + handle_diagnostics(ctx.params.textDocument.uri, ctx.client_id, result.items, true, config) end --- Clear push diagnostics and diagnostic cache. -- cgit From eac7e3fc6c738d7023c104f09341dbb10bf3c4bc Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Sat, 10 Feb 2024 14:04:44 -0800 Subject: refactor(lsp): add vim.lsp.sync.Range type --- runtime/lua/vim/lsp/sync.lua | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua index 7eed542667..62fa0b33f4 100644 --- a/runtime/lua/vim/lsp/sync.lua +++ b/runtime/lua/vim/lsp/sync.lua @@ -120,6 +120,11 @@ local function align_end_position(line, byte, offset_encoding) return byte, char end +---@class vim.lsp.sync.Range +---@field line_idx integer +---@field byte_idx integer +---@field char_idx integer + --- Finds the first line, byte, and char index of the difference between the previous and current lines buffer normalized to the previous codepoint. ---@param prev_lines string[] list of lines from previous buffer ---@param curr_lines string[] list of lines from current buffer @@ -127,7 +132,7 @@ end ---@param lastline integer lastline from on_lines, adjusted to 1-index ---@param new_lastline integer new_lastline from on_lines, adjusted to 1-index ---@param offset_encoding string utf-8|utf-16|utf-32|nil (fallback to utf-8) ----@return table result table include line_idx, byte_idx, and char_idx of first change position +---@return vim.lsp.sync.Range result table include line_idx, byte_idx, and char_idx of first change position local function compute_start_range( prev_lines, curr_lines, @@ -200,15 +205,14 @@ end --- prev_end_range is the text range sent to the server representing the changed region. --- curr_end_range is the text that should be collected and sent to the server. -- ----@param start_range table ---@param prev_lines string[] list of lines ---@param curr_lines string[] list of lines +---@param start_range vim.lsp.sync.Range ---@param firstline integer ---@param lastline integer ---@param new_lastline integer ---@param offset_encoding string ----@return integer|table end_line_idx and end_col_idx of range ----@return table|nil end_col_idx of range +---@return vim.lsp.sync.Range, vim.lsp.sync.Range local function compute_end_range( prev_lines, curr_lines, @@ -285,7 +289,7 @@ local function compute_end_range( local prev_end_range = { line_idx = prev_line_idx, byte_idx = prev_byte_idx, char_idx = prev_char_idx } - local curr_end_range + local curr_end_range ---@type vim.lsp.sync.Range -- Deletion event, new_range cannot be before start if curr_line_idx < start_line_idx then curr_end_range = { line_idx = start_line_idx, byte_idx = 1, char_idx = 1 } @@ -346,8 +350,8 @@ end -- Line endings count here as 2 chars for \r\n (dos), 1 char for \n (unix), and 1 char for \r (mac) -- These correspond to Windows, Linux/macOS (OSX and newer), and macOS (version 9 and prior) ---@param lines string[] ----@param start_range table ----@param end_range table +---@param start_range vim.lsp.sync.Range +---@param end_range vim.lsp.sync.Range ---@param offset_encoding string ---@param line_ending string ---@return integer -- cgit From ed1b66bd998b98ee8cf76b5a23c323352588dd56 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sun, 11 Feb 2024 12:37:20 +0000 Subject: refactor(lsp): move more code to client.lua The dispatchers used by the RPC client should be defined in the client, so they have been moved there. Due to this, it also made sense to move all code related to client configuration and the creation of the RPC client there too. Now vim.lsp.start_client is significantly simplified and now mostly contains logic for tracking open clients. - Renamed client.new -> client.start --- runtime/lua/vim/lsp.lua | 475 ++++++++++------------------------------- runtime/lua/vim/lsp/client.lua | 262 +++++++++++++++++++++-- runtime/lua/vim/lsp/rpc.lua | 17 +- 3 files changed, 353 insertions(+), 401 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 7d8b7e50a3..13f2c92cc2 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1,8 +1,4 @@ ----@diagnostic disable: invisible local api = vim.api -local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_exec_autocmds = - api.nvim_err_writeln, api.nvim_buf_get_lines, api.nvim_command, api.nvim_exec_autocmds -local uv = vim.uv local tbl_isempty, tbl_extend = vim.tbl_isempty, vim.tbl_extend local validate = vim.validate local if_nil = vim.F.if_nil @@ -71,14 +67,6 @@ lsp._request_name_to_capability = { -- TODO improve handling of scratch buffers with LSP attached. ---- Concatenates and writes a list of strings to the Vim error buffer. ---- ----@param ... string List to write to the buffer -local function err_message(...) - nvim_err_writeln(table.concat(vim.tbl_flatten({ ... }))) - nvim_command('redraw') -end - --- Returns the buffer number for the given {bufnr}. --- ---@param bufnr (integer|nil) Buffer number to resolve. Defaults to current buffer @@ -104,30 +92,8 @@ function lsp._unsupported_method(method) return msg end ---- Checks whether a given path is a directory. ---- ----@param filename (string) path to check ----@return boolean # true if {filename} exists and is a directory, false otherwise -local function is_dir(filename) - validate({ filename = { filename, 's' } }) - local stat = uv.fs_stat(filename) - return stat and stat.type == 'directory' or false -end - local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'error' } -local valid_encodings = { - ['utf-8'] = 'utf-8', - ['utf-16'] = 'utf-16', - ['utf-32'] = 'utf-32', - ['utf8'] = 'utf-8', - ['utf16'] = 'utf-16', - ['utf32'] = 'utf-32', - UTF8 = 'utf-8', - UTF16 = 'utf-16', - UTF32 = 'utf-32', -} - local format_line_ending = { ['unix'] = '\n', ['dos'] = '\r\n', @@ -141,14 +107,6 @@ function lsp._buf_get_line_ending(bufnr) return format_line_ending[vim.bo[bufnr].fileformat] or '\n' end -local client_index = 0 ---- Returns a new, unused client id. ---- ----@return integer client_id -local function next_client_id() - client_index = client_index + 1 - return client_index -end -- Tracks all clients created via lsp.start_client local active_clients = {} --- @type table local all_buffer_active_clients = {} --- @type table> @@ -199,115 +157,6 @@ lsp.client_errors = tbl_extend( }) ) ---- Normalizes {encoding} to valid LSP encoding names. ---- ----@param encoding (string) Encoding to normalize ----@return string # normalized encoding name -local function validate_encoding(encoding) - validate({ - encoding = { encoding, 's' }, - }) - return valid_encodings[encoding:lower()] - or error( - string.format( - "Invalid offset encoding %q. Must be one of: 'utf-8', 'utf-16', 'utf-32'", - encoding - ) - ) -end - ----@internal ---- Parses a command invocation into the command itself and its args. If there ---- are no arguments, an empty table is returned as the second argument. ---- ----@param input string[] ----@return string command, string[] args #the command and arguments -function lsp._cmd_parts(input) - validate({ - cmd = { - input, - function() - return vim.tbl_islist(input) - end, - 'list', - }, - }) - - local cmd = input[1] - local cmd_args = {} - -- Don't mutate our input. - for i, v in ipairs(input) do - validate({ ['cmd argument'] = { v, 's' } }) - if i > 1 then - table.insert(cmd_args, v) - end - end - return cmd, cmd_args -end - ---- Augments a validator function with support for optional (nil) values. ---- ----@param fn (fun(v): boolean) The original validator function; should return a ----bool. ----@return fun(v): boolean # The augmented function. Also returns true if {v} is ----`nil`. -local function optional_validator(fn) - return function(v) - return v == nil or fn(v) - end -end - ---- Validates a client configuration as given to |vim.lsp.start_client()|. ---- ----@param config (lsp.ClientConfig) ----@return (string|fun(dispatchers:vim.lsp.rpc.Dispatchers):vim.lsp.rpc.PublicClient?) Command ----@return string[] Arguments ----@return string Encoding. -local function validate_client_config(config) - validate({ - config = { config, 't' }, - }) - validate({ - handlers = { config.handlers, 't', true }, - capabilities = { config.capabilities, 't', true }, - cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), 'directory' }, - cmd_env = { config.cmd_env, 't', true }, - detached = { config.detached, 'b', true }, - name = { config.name, 's', true }, - on_error = { config.on_error, 'f', true }, - on_exit = { config.on_exit, 'f', true }, - on_init = { config.on_init, 'f', true }, - settings = { config.settings, 't', true }, - commands = { config.commands, 't', true }, - before_init = { config.before_init, 'f', true }, - offset_encoding = { config.offset_encoding, 's', true }, - flags = { config.flags, 't', true }, - get_language_id = { config.get_language_id, 'f', true }, - }) - assert( - ( - not config.flags - or not config.flags.debounce_text_changes - or type(config.flags.debounce_text_changes) == 'number' - ), - 'flags.debounce_text_changes must be a number with the debounce time in milliseconds' - ) - - local cmd, cmd_args --- @type (string|fun(dispatchers:vim.lsp.rpc.Dispatchers):vim.lsp.rpc.PublicClient), string[] - local config_cmd = config.cmd - if type(config_cmd) == 'function' then - cmd = config_cmd - else - cmd, cmd_args = lsp._cmd_parts(config_cmd) - end - local offset_encoding = valid_encodings.UTF16 - if config.offset_encoding then - offset_encoding = validate_encoding(config.offset_encoding) - end - - return cmd, cmd_args, offset_encoding -end - ---@private --- Returns full text of buffer {bufnr} as a string. --- @@ -315,7 +164,7 @@ end ---@return string # Buffer text as string. function lsp._buf_get_full_text(bufnr) local line_ending = lsp._buf_get_line_ending(bufnr) - local text = table.concat(nvim_buf_get_lines(bufnr, 0, -1, true), line_ending) + local text = table.concat(api.nvim_buf_get_lines(bufnr, 0, -1, true), line_ending) if vim.bo[bufnr].eol then text = text .. line_ending end @@ -473,8 +322,8 @@ end --- Either use |:au|, |nvim_create_autocmd()| or put the call in a --- `ftplugin/.lua` (See |ftplugin-name|) --- ----@param config table Same configuration as documented in |vim.lsp.start_client()| ----@param opts (nil|lsp.StartOpts) Optional keyword arguments: +---@param config lsp.ClientConfig Same configuration as documented in |vim.lsp.start_client()| +---@param opts lsp.StartOpts? Optional keyword arguments: --- - reuse_client (fun(client: client, config: table): boolean) --- Predicate used to decide if a client should be re-used. --- Used on all running clients. @@ -483,20 +332,16 @@ end --- - bufnr (number) --- Buffer handle to attach to if starting or re-using a --- client (0 for current). ----@return integer|nil client_id +---@return integer? client_id function lsp.start(config, opts) opts = opts or {} local reuse_client = opts.reuse_client or function(client, conf) return client.config.root_dir == conf.root_dir and client.name == conf.name end - if not config.name and type(config.cmd) == 'table' then - config.name = config.cmd[1] and vim.fs.basename(config.cmd[1]) or nil - end - local bufnr = opts.bufnr - if bufnr == nil or bufnr == 0 then - bufnr = api.nvim_get_current_buf() - end + + local bufnr = resolve_bufnr(opts.bufnr) + for _, clients in ipairs({ uninitialized_clients, lsp.get_clients() }) do for _, client in pairs(clients) do if reuse_client(client, config) then @@ -505,10 +350,13 @@ function lsp.start(config, opts) end end end + local client_id = lsp.start_client(config) - if client_id == nil then - return nil -- lsp.start_client will have printed an error + + if not client_id then + return -- lsp.start_client will have printed an error end + lsp.buf_attach_client(bufnr, client_id) return client_id end @@ -599,29 +447,6 @@ function lsp._set_defaults(client, bufnr) end end ---- @class lsp.ClientConfig ---- @field cmd (string[]|fun(dispatchers: table):table) ---- @field cmd_cwd string ---- @field cmd_env (table) ---- @field detached boolean ---- @field workspace_folders (table) ---- @field capabilities lsp.ClientCapabilities ---- @field handlers table ---- @field settings table ---- @field commands table ---- @field init_options table ---- @field name string ---- @field get_language_id fun(bufnr: integer, filetype: string): string ---- @field offset_encoding string ---- @field on_error fun(code: integer) ---- @field before_init function ---- @field on_init function ---- @field on_exit fun(code: integer, signal: integer, client_id: integer) ---- @field on_attach fun(client: lsp.Client, bufnr: integer) ---- @field trace 'off'|'messages'|'verbose'|nil ---- @field flags table ---- @field root_dir string - --- Reset defaults set by `set_defaults`. --- Must only be called if the last client attached to a buffer exits. local function reset_defaults(bufnr) @@ -642,6 +467,90 @@ local function reset_defaults(bufnr) end) end +--- @param client lsp.Client +local function on_client_init(client) + local id = client.id + uninitialized_clients[id] = nil + -- Only assign after initialized. + active_clients[id] = client + -- If we had been registered before we start, then send didOpen This can + -- happen if we attach to buffers before initialize finishes or if + -- someone restarts a client. + for bufnr, client_ids in pairs(all_buffer_active_clients) do + if client_ids[id] then + client.on_attach(bufnr) + end + end +end + +--- @param code integer +--- @param signal integer +--- @param client_id integer +local function on_client_exit(code, signal, client_id) + local client = active_clients[client_id] or uninitialized_clients[client_id] + + for bufnr, client_ids in pairs(all_buffer_active_clients) do + if client_ids[client_id] then + vim.schedule(function() + if client and client.attached_buffers[bufnr] then + api.nvim_exec_autocmds('LspDetach', { + buffer = bufnr, + modeline = false, + data = { client_id = client_id }, + }) + end + + local namespace = vim.lsp.diagnostic.get_namespace(client_id) + vim.diagnostic.reset(namespace, bufnr) + + client_ids[client_id] = nil + if vim.tbl_isempty(client_ids) then + reset_defaults(bufnr) + end + end) + end + end + + local name = client.name or 'unknown' + + -- Schedule the deletion of the client object so that it exists in the execution of LspDetach + -- autocommands + vim.schedule(function() + active_clients[client_id] = nil + uninitialized_clients[client_id] = nil + + -- Client can be absent if executable starts, but initialize fails + -- init/attach won't have happened + if client then + changetracking.reset(client) + end + if code ~= 0 or (signal ~= 0 and signal ~= 15) then + local msg = string.format( + 'Client %s quit with exit code %s and signal %s. Check log for errors: %s', + name, + code, + signal, + lsp.get_log_path() + ) + vim.notify(msg, vim.log.levels.WARN) + end + end) +end + +--- @generic F: function +--- @param ... F +--- @return F +local function join_cbs(...) + local funcs = vim.F.pack_len(...) + return function(...) + for i = 1, funcs.n do + if funcs[i] ~= nil then + funcs[i](...) + end + end + end +end + -- FIXME: DOC: Currently all methods on the `vim.lsp.client` object are -- documented twice: Here, and on the methods themselves (e.g. -- `client.request()`). This is a workaround for the vimdoc generator script @@ -762,192 +671,22 @@ end --- fully initialized. Use `on_init` to do any actions once --- the client has been initialized. function lsp.start_client(config) - local cmd, cmd_args, offset_encoding = validate_client_config(config) - - config.flags = config.flags or {} - config.settings = config.settings or {} - - -- By default, get_language_id just returns the exact filetype it is passed. - -- It is possible to pass in something that will calculate a different filetype, - -- to be sent by the client. - config.get_language_id = config.get_language_id or function(_, filetype) - return filetype - end - - local client_id = next_client_id() - - local handlers = config.handlers or {} - local name = config.name or tostring(client_id) - local log_prefix = string.format('LSP[%s]', name) - - local dispatch = {} - - --- Returns the handler associated with an LSP method. - --- Returns the default handler if the user hasn't set a custom one. - --- - ---@param method (string) LSP method name - ---@return lsp.Handler|nil handler for the given method, if defined, or the default from |vim.lsp.handlers| - local function resolve_handler(method) - return handlers[method] or lsp.handlers[method] - end - - ---@private - --- Handles a notification sent by an LSP server by invoking the - --- corresponding handler. - --- - ---@param method (string) LSP method name - ---@param params (table) The parameters for that method. - function dispatch.notification(method, params) - log.trace('notification', method, params) - local handler = resolve_handler(method) - if handler then - -- Method name is provided here for convenience. - handler(nil, params, { method = method, client_id = client_id }) - end - end + config = vim.deepcopy(config, false) + config.on_init = join_cbs(config.on_init, on_client_init) + config.on_exit = join_cbs(config.on_exit, on_client_exit) - ---@private - --- Handles a request from an LSP server by invoking the corresponding handler. - --- - ---@param method (string) LSP method name - ---@param params (table) The parameters for that method - ---@return any result - ---@return lsp.ResponseError error code and message set in case an exception happens during the request. - function dispatch.server_request(method, params) - log.trace('server_request', method, params) - local handler = resolve_handler(method) - if handler then - log.trace('server_request: found handler for', method) - return handler(nil, params, { method = method, client_id = client_id }) - end - log.warn('server_request: no handler found for', method) - return nil, lsp.rpc_response_error(protocol.ErrorCodes.MethodNotFound) - end - - --- Logs the given error to the LSP log and to the error buffer. - --- @param code integer Error code - --- @param err any Error arguments - local function write_error(code, err) - log.error(log_prefix, 'on_error', { code = lsp.client_errors[code], err = err }) - err_message(log_prefix, ': Error ', lsp.client_errors[code], ': ', vim.inspect(err)) - end + local client = require('vim.lsp.client').start(config) - ---@private - --- Invoked when the client operation throws an error. - --- - ---@param code (integer) Error code - ---@param err any Other arguments may be passed depending on the error kind - ---@see vim.lsp.rpc.client_errors for possible errors. Use - ---`vim.lsp.rpc.client_errors[code]` to get a human-friendly name. - function dispatch.on_error(code, err) - write_error(code, err) - if config.on_error then - local status, usererr = pcall(config.on_error, code, err) - if not status then - log.error(log_prefix, 'user on_error failed', { err = usererr }) - err_message(log_prefix, ' user on_error failed: ', tostring(usererr)) - end - end - end - - ---@private - --- Invoked on client exit. - --- - ---@param code (integer) exit code of the process - ---@param signal (integer) the signal used to terminate (if any) - function dispatch.on_exit(code, signal) - if config.on_exit then - pcall(config.on_exit, code, signal, client_id) - end - - local client = active_clients[client_id] and active_clients[client_id] - or uninitialized_clients[client_id] - - for bufnr, client_ids in pairs(all_buffer_active_clients) do - if client_ids[client_id] then - vim.schedule(function() - if client and client.attached_buffers[bufnr] then - nvim_exec_autocmds('LspDetach', { - buffer = bufnr, - modeline = false, - data = { client_id = client_id }, - }) - end - - local namespace = vim.lsp.diagnostic.get_namespace(client_id) - vim.diagnostic.reset(namespace, bufnr) - - client_ids[client_id] = nil - if vim.tbl_isempty(client_ids) then - reset_defaults(bufnr) - end - end) - end - end - - -- Schedule the deletion of the client object so that it exists in the execution of LspDetach - -- autocommands - vim.schedule(function() - active_clients[client_id] = nil - uninitialized_clients[client_id] = nil - - -- Client can be absent if executable starts, but initialize fails - -- init/attach won't have happened - if client then - changetracking.reset(client) - end - if code ~= 0 or (signal ~= 0 and signal ~= 15) then - local msg = string.format( - 'Client %s quit with exit code %s and signal %s. Check log for errors: %s', - name, - code, - signal, - lsp.get_log_path() - ) - vim.notify(msg, vim.log.levels.WARN) - end - end) - end - - -- Start the RPC client. - local rpc --- @type vim.lsp.rpc.PublicClient? - if type(cmd) == 'function' then - rpc = cmd(dispatch) - else - rpc = lsp.rpc.start(cmd, cmd_args, dispatch, { - cwd = config.cmd_cwd, - env = config.cmd_env, - detached = config.detached, - }) - end - - -- Return nil if client fails to start - if not rpc then + if not client then return end - config.capabilities = config.capabilities or protocol.make_client_capabilities() - - local client = require('vim.lsp.client').new(client_id, rpc, handlers, offset_encoding, config) - -- Store the uninitialized_clients for cleanup in case we exit before initialize finishes. - uninitialized_clients[client_id] = client + -- TODO(lewis6991): do this on before_init(). Requires API change to before_init() so it + -- can access the client_id. + uninitialized_clients[client.id] = client - client:initialize(function() - uninitialized_clients[client_id] = nil - -- Only assign after initialized. - active_clients[client_id] = client - -- If we had been registered before we start, then send didOpen This can - -- happen if we attach to buffers before initialize finishes or if - -- someone restarts a client. - for bufnr, client_ids in pairs(all_buffer_active_clients) do - if client_ids[client_id] then - client.on_attach(bufnr) - end - end - end) - - return client_id + return client.id end --- Notify all attached clients that a buffer has changed. @@ -1149,7 +888,7 @@ function lsp.buf_detach_client(bufnr, client_id) return end - nvim_exec_autocmds('LspDetach', { + api.nvim_exec_autocmds('LspDetach', { buffer = bufnr, modeline = false, data = { client_id = client_id }, @@ -1372,7 +1111,7 @@ function lsp.buf_request(bufnr, method, params, handler) -- if has client but no clients support the given method, notify the user if next(clients) and not method_supported then vim.notify(lsp._unsupported_method(method), vim.log.levels.ERROR) - nvim_command('redraw') + vim.cmd.redraw() return {}, function() end end diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index 7bf83f4d2c..58db4387b6 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -4,6 +4,30 @@ local lsp = vim.lsp local log = lsp.log local ms = lsp.protocol.Methods local changetracking = lsp._changetracking +local validate = vim.validate + +--- @class lsp.ClientConfig +--- @field cmd (string[]|fun(dispatchers: table):table) +--- @field cmd_cwd string +--- @field cmd_env (table) +--- @field detached boolean +--- @field workspace_folders (table) +--- @field capabilities lsp.ClientCapabilities +--- @field handlers table +--- @field settings table +--- @field commands table +--- @field init_options table +--- @field name? string +--- @field get_language_id fun(bufnr: integer, filetype: string): string +--- @field offset_encoding string +--- @field on_error fun(code: integer) +--- @field before_init fun(params: lsp.InitializeParams, config: lsp.ClientConfig) +--- @field on_init fun(client: lsp.Client, initialize_result: lsp.InitializeResult) +--- @field on_exit fun(code: integer, signal: integer, client_id: integer) +--- @field on_attach fun(client: lsp.Client, bufnr: integer) +--- @field trace 'off'|'messages'|'verbose'|nil +--- @field flags table +--- @field root_dir string --- @class lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}> --- @field pending table @@ -51,7 +75,6 @@ local changetracking = lsp._changetracking --- @field initialized true? --- @field workspace_folders lsp.WorkspaceFolder[]? --- @field attached_buffers table ---- @field commands table --- @field private _log_prefix string --- Track this so that we can escalate automatically if we've already tried a --- graceful shutdown @@ -119,27 +142,131 @@ local function method_wrapper(cls, meth) end end +local client_index = 0 + +--- Checks whether a given path is a directory. +--- @param filename (string) path to check +--- @return boolean # true if {filename} exists and is a directory, false otherwise +local function is_dir(filename) + validate({ filename = { filename, 's' } }) + local stat = uv.fs_stat(filename) + return stat and stat.type == 'directory' or false +end + +local valid_encodings = { + ['utf-8'] = 'utf-8', + ['utf-16'] = 'utf-16', + ['utf-32'] = 'utf-32', + ['utf8'] = 'utf-8', + ['utf16'] = 'utf-16', + ['utf32'] = 'utf-32', + UTF8 = 'utf-8', + UTF16 = 'utf-16', + UTF32 = 'utf-32', +} + +--- Normalizes {encoding} to valid LSP encoding names. +--- @param encoding string? Encoding to normalize +--- @return string # normalized encoding name +local function validate_encoding(encoding) + validate({ + encoding = { encoding, 's', true }, + }) + if not encoding then + return valid_encodings.UTF16 + end + return valid_encodings[encoding:lower()] + or error( + string.format( + "Invalid offset encoding %q. Must be one of: 'utf-8', 'utf-16', 'utf-32'", + encoding + ) + ) +end + +--- Augments a validator function with support for optional (nil) values. +--- @param fn (fun(v): boolean) The original validator function; should return a +--- bool. +--- @return fun(v): boolean # The augmented function. Also returns true if {v} is +--- `nil`. +local function optional_validator(fn) + return function(v) + return v == nil or fn(v) + end +end + +--- Validates a client configuration as given to |vim.lsp.start_client()|. +--- @param config lsp.ClientConfig +local function process_client_config(config) + validate({ + config = { config, 't' }, + }) + validate({ + handlers = { config.handlers, 't', true }, + capabilities = { config.capabilities, 't', true }, + cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), 'directory' }, + cmd_env = { config.cmd_env, 't', true }, + detached = { config.detached, 'b', true }, + name = { config.name, 's', true }, + on_error = { config.on_error, 'f', true }, + on_exit = { config.on_exit, 'f', true }, + on_init = { config.on_init, 'f', true }, + settings = { config.settings, 't', true }, + commands = { config.commands, 't', true }, + before_init = { config.before_init, 'f', true }, + offset_encoding = { config.offset_encoding, 's', true }, + flags = { config.flags, 't', true }, + get_language_id = { config.get_language_id, 'f', true }, + }) + assert( + ( + not config.flags + or not config.flags.debounce_text_changes + or type(config.flags.debounce_text_changes) == 'number' + ), + 'flags.debounce_text_changes must be a number with the debounce time in milliseconds' + ) + + if not config.name and type(config.cmd) == 'table' then + config.name = config.cmd[1] and vim.fs.basename(config.cmd[1]) or nil + end + + config.offset_encoding = validate_encoding(config.offset_encoding) + config.flags = config.flags or {} + config.settings = config.settings or {} + config.handlers = config.handlers or {} + + -- By default, get_language_id just returns the exact filetype it is passed. + -- It is possible to pass in something that will calculate a different filetype, + -- to be sent by the client. + config.get_language_id = config.get_language_id or function(_, filetype) + return filetype + end + + config.capabilities = config.capabilities or lsp.protocol.make_client_capabilities() + config.commands = config.commands or {} +end + --- @package ---- @param id integer ---- @param rpc vim.lsp.rpc.PublicClient ---- @param handlers table ---- @param offset_encoding string --- @param config lsp.ClientConfig ---- @return lsp.Client -function Client.new(id, rpc, handlers, offset_encoding, config) +--- @return lsp.Client? +function Client.start(config) + process_client_config(config) + + client_index = client_index + 1 + local id = client_index + local name = config.name or tostring(id) --- @class lsp.Client local self = { id = id, config = config, - handlers = handlers, - rpc = rpc, - offset_encoding = offset_encoding, + handlers = config.handlers, + offset_encoding = config.offset_encoding, name = name, _log_prefix = string.format('LSP[%s]', name), requests = {}, - commands = config.commands or {}, attached_buffers = {}, server_capabilities = {}, dynamic_capabilities = vim.lsp._dynamic.new(id), @@ -165,15 +292,46 @@ function Client.new(id, rpc, handlers, offset_encoding, config) self.on_attach = method_wrapper(self, Client._on_attach) self.supports_method = method_wrapper(self, Client._supports_method) - ---@type table title of unfinished progress sequences by token + --- @type table title of unfinished progress sequences by token self.progress.pending = {} - return setmetatable(self, Client) + --- @type vim.lsp.rpc.Dispatchers + local dispatchers = { + notification = method_wrapper(self, Client._notification), + server_request = method_wrapper(self, Client._server_request), + on_error = method_wrapper(self, Client._on_error), + on_exit = method_wrapper(self, Client._on_exit), + } + + -- Start the RPC client. + local rpc --- @type vim.lsp.rpc.PublicClient? + local config_cmd = config.cmd + if type(config_cmd) == 'function' then + rpc = config_cmd(dispatchers) + else + rpc = lsp.rpc.start(config_cmd, dispatchers, { + cwd = config.cmd_cwd, + env = config.cmd_env, + detached = config.detached, + }) + end + + -- Return nil if the rpc client fails to start + if not rpc then + return + end + + self.rpc = rpc + + setmetatable(self, Client) + + self:initialize() + + return self end --- @private ---- @param cb fun() -function Client:initialize(cb) +function Client:initialize() local valid_traces = { off = 'off', messages = 'messages', @@ -282,8 +440,6 @@ function Client:initialize(cb) 'server_capabilities', { server_capabilities = self.server_capabilities } ) - - cb() end) end @@ -302,7 +458,7 @@ end --- @param bufnr (integer|nil) Buffer number to resolve. Defaults to current buffer --- @return integer bufnr local function resolve_bufnr(bufnr) - vim.validate({ bufnr = { bufnr, 'n', true } }) + validate({ bufnr = { bufnr, 'n', true } }) if bufnr == nil or bufnr == 0 then return api.nvim_get_current_buf() end @@ -374,10 +530,9 @@ end -- TODO(lewis6991): duplicated from lsp.lua local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'error' } --- TODO(lewis6991): duplicated from lsp.lua --- Concatenates and writes a list of strings to the Vim error buffer. --- ----@param ... string List to write to the buffer +--- @param ... string List to write to the buffer local function err_message(...) api.nvim_err_writeln(table.concat(vim.tbl_flatten({ ... }))) api.nvim_command('redraw') @@ -461,7 +616,7 @@ end --- @return boolean status true if notification was successful. false otherwise --- @see |vim.lsp.client.notify()| function Client:_cancel_request(id) - vim.validate({ id = { id, 'n' } }) + validate({ id = { id, 'n' } }) local request = self.requests[id] if request and request.type == 'pending' then request.type = 'cancel' @@ -527,7 +682,7 @@ function Client:_exec_cmd(command, context, handler) context.bufnr = context.bufnr or api.nvim_get_current_buf() context.client_id = self.id local cmdname = command.command - local fn = self.commands[cmdname] or lsp.commands[cmdname] + local fn = self.config.commands[cmdname] or lsp.commands[cmdname] if fn then fn(command, context) return @@ -654,4 +809,67 @@ function Client:_supports_method(method, opts) end end +--- @private +--- Handles a notification sent by an LSP server by invoking the +--- corresponding handler. +--- +--- @param method string LSP method name +--- @param params table The parameters for that method. +function Client:_notification(method, params) + log.trace('notification', method, params) + local handler = self:_resolve_handler(method) + if handler then + -- Method name is provided here for convenience. + handler(nil, params, { method = method, client_id = self.id }) + end +end + +--- @private +--- Handles a request from an LSP server by invoking the corresponding handler. +--- +--- @param method (string) LSP method name +--- @param params (table) The parameters for that method +--- @return any result +--- @return lsp.ResponseError error code and message set in case an exception happens during the request. +function Client:_server_request(method, params) + log.trace('server_request', method, params) + local handler = self:_resolve_handler(method) + if handler then + log.trace('server_request: found handler for', method) + return handler(nil, params, { method = method, client_id = self.id }) + end + log.warn('server_request: no handler found for', method) + return nil, lsp.rpc_response_error(lsp.protocol.ErrorCodes.MethodNotFound) +end + +--- @private +--- Invoked when the client operation throws an error. +--- +--- @param code integer Error code +--- @param err any Other arguments may be passed depending on the error kind +--- @see vim.lsp.rpc.client_errors for possible errors. Use +--- `vim.lsp.rpc.client_errors[code]` to get a human-friendly name. +function Client:_on_error(code, err) + self:write_error(code, err) + if self.config.on_error then + --- @type boolean, string + local status, usererr = pcall(self.config.on_error, code, err) + if not status then + log.error(self._log_prefix, 'user on_error failed', { err = usererr }) + err_message(self._log_prefix, ' user on_error failed: ', tostring(usererr)) + end + end +end + +--- @private +--- Invoked on client exit. +--- +--- @param code integer) exit code of the process +--- @param signal integer the signal used to terminate (if any) +function Client:_on_exit(code, signal) + if self.config.on_exit then + pcall(self.config.on_exit, code, signal, self.id) + end +end + return Client diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 23f70826e5..e849bb4f2a 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -732,8 +732,7 @@ end --- interact with it. Communication with the spawned process happens via stdio. For --- communication via TCP, spawn a process manually and use |vim.lsp.rpc.connect()| --- ----@param cmd string Command to start the LSP server. ----@param cmd_args string[] List of additional string arguments to pass to {cmd}. +---@param cmd string[] Command to start the LSP server. --- ---@param dispatchers? vim.lsp.rpc.Dispatchers Dispatchers for LSP message types. --- Valid dispatcher names are: @@ -754,12 +753,11 @@ end --- - `request()` |vim.lsp.rpc.request()| --- - `is_closing()` returns a boolean indicating if the RPC is closing. --- - `terminate()` terminates the RPC client. -function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) - log.info('Starting RPC client', { cmd = cmd, args = cmd_args, extra = extra_spawn_params }) +function M.start(cmd, dispatchers, extra_spawn_params) + log.info('Starting RPC client', { cmd = cmd, extra = extra_spawn_params }) validate({ - cmd = { cmd, 's' }, - cmd_args = { cmd_args, 't' }, + cmd = { cmd, 't' }, dispatchers = { dispatchers, 't', true }, }) @@ -795,7 +793,7 @@ function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) local stderr_handler = function(_, chunk) if chunk then - log.error('rpc', cmd, 'stderr', chunk) + log.error('rpc', cmd[1], 'stderr', chunk) end end @@ -804,10 +802,7 @@ function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) detached = extra_spawn_params.detached end - local cmd1 = { cmd } - vim.list_extend(cmd1, cmd_args) - - local ok, sysobj_or_err = pcall(vim.system, cmd1, { + local ok, sysobj_or_err = pcall(vim.system, cmd, { stdin = true, stdout = stdout_handler, stderr = stderr_handler, -- cgit From 917172dd9680cc4234a47beee91e8adcaf0e833c Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sun, 11 Feb 2024 18:07:04 +0000 Subject: fix(lsp): semantic token defer loading Fixes #27424 --- runtime/lua/vim/lsp/handlers.lua | 5 +++++ runtime/lua/vim/lsp/semantic_tokens.lua | 6 ++---- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 2fa539d963..4bb14e5a09 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -644,6 +644,11 @@ M[ms.workspace_inlayHint_refresh] = function(err, result, ctx, config) return vim.lsp.inlay_hint.on_refresh(err, result, ctx, config) end +---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#semanticTokens_refreshRequest +M[ms.workspace_semanticTokens_refresh] = function(err, result, ctx, _config) + return vim.lsp.semantic_tokens._refresh(err, result, ctx) +end + -- Add boilerplate error validation and logging for all of these. for k, fn in pairs(M) do M[k] = function(err, result, ctx, config) diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index b0cec0dd0e..fe8638bdfa 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -1,6 +1,5 @@ local api = vim.api local bit = require('bit') -local handlers = require('vim.lsp.handlers') local ms = require('vim.lsp.protocol').Methods local util = require('vim.lsp.util') local uv = vim.uv @@ -763,6 +762,7 @@ function M.highlight_token(token, bufnr, client_id, hl_group, opts) }) end +--- @package --- |lsp-handler| for the method `workspace/semanticTokens/refresh` --- --- Refresh requests are sent by the server to indicate a project-wide change @@ -770,9 +770,7 @@ end --- invalidate the current results of all buffers and automatically kick off a --- new request for buffers that are displayed in a window. For those that aren't, a --- the BufWinEnter event should take care of it next time it's displayed. ---- ----@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#semanticTokens_refreshRequest -handlers[ms.workspace_semanticTokens_refresh] = function(err, _, ctx) +function M._refresh(err, _, ctx) if err then return vim.NIL end -- cgit From 6c168c0f4d777d7586b47a05d2539210ce711f1c Mon Sep 17 00:00:00 2001 From: altermo <107814000+altermo@users.noreply.github.com> Date: Mon, 12 Feb 2024 13:03:53 +0100 Subject: docs: correct on_key docs (#27429) --- runtime/lua/vim/_editor.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index c130eb1958..c5a6e65e86 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -652,8 +652,9 @@ local on_key_cbs = {} ---@note {fn} will not be cleared by |nvim_buf_clear_namespace()| ---@note {fn} will receive the keys after mappings have been evaluated --- ----@param fn fun(key: string) Function invoked on every key press. |i_CTRL-V| ---- Returning nil removes the callback associated with namespace {ns_id}. +---@param fn fun(key: string)? Function invoked on every key press. |i_CTRL-V| +--- Passing in nil when {ns_id} is specified removes the +--- callback associated with namespace {ns_id}. ---@param ns_id integer? Namespace ID. If nil or 0, generates and returns a --- new |nvim_create_namespace()| id. --- -- cgit From 597ecf751603cde2d5f58021d503ae20a12eb2f2 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 12 Feb 2024 10:18:42 +0000 Subject: fix(lsp): re-add client.commands and mark private --- runtime/lua/vim/lsp/client.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index 58db4387b6..a279be55e9 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -79,6 +79,7 @@ local validate = vim.validate --- Track this so that we can escalate automatically if we've already tried a --- graceful shutdown --- @field private _graceful_shutdown_failed true? +--- @field private commands table --- --- @field dynamic_capabilities lsp.DynamicCapabilities --- @@ -270,6 +271,7 @@ function Client.start(config) attached_buffers = {}, server_capabilities = {}, dynamic_capabilities = vim.lsp._dynamic.new(id), + commands = config.commands, -- Remove in Nvim 0.11 --- Contains $/progress report messages. --- They have the format {token: integer|string, value: any} -- cgit From 1c7b0b9d5f874fe962a8e63d9e8db7e576ab0d48 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Mon, 12 Feb 2024 20:15:27 -0800 Subject: docs: stricter bufname and bufnr types (#27454) --- runtime/lua/vim/_meta/vimfn.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index acf3750500..224cecf144 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -582,7 +582,7 @@ function vim.fn.bufloaded(buf) end --- echo bufname("file2") " name of buffer where "file2" matches. --- < --- ---- @param buf? any +--- @param buf? integer|string --- @return string function vim.fn.bufname(buf) end @@ -599,7 +599,7 @@ function vim.fn.bufname(buf) end --- number necessarily exist, because ":bwipeout" may have removed --- them. Use bufexists() to test for the existence of a buffer. --- ---- @param buf? any +--- @param buf? integer|string --- @param create? any --- @return integer function vim.fn.bufnr(buf, create) end -- cgit From 309c36d3c9f80e2999b8a66c8a2a1ea640e84562 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Tue, 13 Feb 2024 02:33:09 -0500 Subject: docs(builtin): fix lua types for vim.fn.sign_getplaced Per :help sign_getplaced(): - Parameter {dict}: lnum also accepts integer as well as string - Return value: item has field bufnr, not buf --- runtime/lua/vim/_meta/builtin_types.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/builtin_types.lua b/runtime/lua/vim/_meta/builtin_types.lua index e74cf86173..0bbc3e9bc8 100644 --- a/runtime/lua/vim/_meta/builtin_types.lua +++ b/runtime/lua/vim/_meta/builtin_types.lua @@ -81,10 +81,10 @@ --- @class vim.fn.sign_getplaced.dict --- @field group? string --- @field id? integer ---- @field lnum? string +--- @field lnum? string|integer --- @class vim.fn.sign_getplaced.ret.item ---- @field buf integer +--- @field bufnr integer --- @field signs vim.fn.sign[] --- @class vim.fn.sign_place.dict -- cgit From 89135cff030b06f60cd596a9ae81cd9583987517 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Mon, 12 Feb 2024 21:38:37 -0500 Subject: fix(loader): remove cyclic dependency on vim.fs (when --luamod-dev) Problem: Loading `vim.fs` via the `vim.loader` Lua package loader will result in a stack overflow due to a cyclic dependency. This may happen when the `vim.fs` module isn't byte-compiled, i.e. when `--luamod-dev` is used (#27413). Solution: `vim.loader` depends on `vim.fs`. Therefore `vim.fs` should be loaded in advance. --- runtime/lua/vim/loader.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/loader.lua b/runtime/lua/vim/loader.lua index b77251cf7e..ec99e417c2 100644 --- a/runtime/lua/vim/loader.lua +++ b/runtime/lua/vim/loader.lua @@ -1,3 +1,4 @@ +local fs = vim.fs -- "vim.fs" is a dependency, so must be loaded early. local uv = vim.uv local uri_encode = vim.uri_encode --- @type function @@ -63,7 +64,7 @@ function Loader.get_hash(path) end local function normalize(path) - return vim.fs.normalize(path, { expand_env = false }) + return fs.normalize(path, { expand_env = false }) end --- Gets the rtp excluding after directories. @@ -432,7 +433,7 @@ end function Loader.lsmod(path) if not Loader._indexed[path] then Loader._indexed[path] = {} - for name, t in vim.fs.dir(path .. '/lua') do + for name, t in fs.dir(path .. '/lua') do local modpath = path .. '/lua/' .. name -- HACK: type is not always returned due to a bug in luv t = t or Loader.get_hash(modpath).type -- cgit From 1a3a8d903e9705ce41867e1cbc629a85c7cb6252 Mon Sep 17 00:00:00 2001 From: bfredl Date: Sun, 11 Feb 2024 19:13:38 +0100 Subject: refactor(lua): use a keyset for vim.diff opts parsing --- runtime/lua/vim/_meta/api_keysets.lua | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index 0442a89e3f..ab0d3aafe8 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -297,3 +297,17 @@ error('Cannot require a meta file') --- @field end_row? integer --- @field start_vcol? integer --- @field end_vcol? integer + +--- @class vim.api.keyset.xdl_diff +--- @field on_hunk? function +--- @field result_type? string +--- @field algorithm? string +--- @field ctxlen? integer +--- @field interhunkctxlen? integer +--- @field linematch? any +--- @field ignore_whitespace? boolean +--- @field ignore_whitespace_change? boolean +--- @field ignore_whitespace_change_at_eol? boolean +--- @field ignore_cr_at_eol? boolean +--- @field ignore_blank_lines? boolean +--- @field indent_heuristic? boolean -- cgit From 9f8c96240dc0318bd92a646966917e8fe0641144 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 12 Feb 2024 13:46:32 +0000 Subject: refactor(lsp): resolve the config-client entanglement Previously the LSP-Client object contained some fields that are also in the client config, but for a lot of other fields, the config was used directly making the two objects vaguely entangled with either not having a clear role. Now the config object is treated purely as config (read-only) from the client, and any fields the client needs from the config are now copied in as additional fields. This means: - the config object is no longet normalised and is left as the user provided it. - the client only reads the config on creation of the client and all other implementations now read the clients version of the fields. In addition, internal support for multiple callbacks has been added to the client so the client tracking logic (done in lua.lsp) can be done more robustly instead of wrapping the user callbacks which may error. --- runtime/lua/vim/_meta.lua | 2 + runtime/lua/vim/lsp.lua | 61 ++++--- runtime/lua/vim/lsp/_changetracking.lua | 6 +- runtime/lua/vim/lsp/_dynamic.lua | 4 +- runtime/lua/vim/lsp/_watchfiles.lua | 8 +- runtime/lua/vim/lsp/client.lua | 307 +++++++++++++++++++------------- runtime/lua/vim/lsp/codelens.lua | 1 - runtime/lua/vim/lsp/handlers.lua | 4 +- runtime/lua/vim/lsp/health.lua | 2 +- 9 files changed, 230 insertions(+), 165 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta.lua b/runtime/lua/vim/_meta.lua index 4c50627fe4..731dd5b923 100644 --- a/runtime/lua/vim/_meta.lua +++ b/runtime/lua/vim/_meta.lua @@ -1,5 +1,7 @@ --- @meta +--- @alias elem_or_list T|T[] + ---@type uv vim.uv = ... diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 13f2c92cc2..8608bdfa57 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -143,6 +143,14 @@ local function for_each_buffer_client(bufnr, fn, restrict_client_ids) end end +local client_errors_base = table.maxn(lsp.rpc.client_errors) +local client_errors_offset = 0 + +local function new_error_index() + client_errors_offset = client_errors_offset + 1 + return client_errors_base + client_errors_offset +end + --- Error codes to be used with `on_error` from |vim.lsp.start_client|. --- Can be used to look up the string from a the number or the number --- from the string. @@ -151,9 +159,10 @@ lsp.client_errors = tbl_extend( 'error', lsp.rpc.client_errors, vim.tbl_add_reverse_lookup({ - BEFORE_INIT_CALLBACK_ERROR = table.maxn(lsp.rpc.client_errors) + 1, - ON_INIT_CALLBACK_ERROR = table.maxn(lsp.rpc.client_errors) + 2, - ON_ATTACH_ERROR = table.maxn(lsp.rpc.client_errors) + 3, + BEFORE_INIT_CALLBACK_ERROR = new_error_index(), + ON_INIT_CALLBACK_ERROR = new_error_index(), + ON_ATTACH_ERROR = new_error_index(), + ON_EXIT_CALLBACK_ERROR = new_error_index(), }) ) @@ -262,6 +271,10 @@ end --- --- - {handlers} (table): The handlers used by the client as described in |lsp-handler|. --- +--- - {commands} (table): Table of command name to function which is called if +--- any LSP action (code action, code lenses, ...) triggers the command. +--- Client commands take precedence over the global command registry. +--- --- - {requests} (table): The current pending requests in flight --- to the server. Entries are key-value pairs with the key --- being the request ID while the value is a table with `type`, @@ -270,7 +283,7 @@ end --- be "complete" ephemerally while executing |LspRequest| autocmds --- when replies are received from the server. --- ---- - {config} (table): copy of the table that was passed by the user +--- - {config} (table): Reference of the table that was passed by the user --- to |vim.lsp.start_client()|. --- --- - {server_capabilities} (table): Response from the server sent on @@ -278,6 +291,11 @@ end --- --- - {progress} A ring buffer (|vim.ringbuf()|) containing progress messages --- sent by the server. +--- +--- - {settings} Map with language server specific settings. +--- See {config} in |vim.lsp.start_client()| +--- +--- - {flags} A table with flags for the client. See {config} in |vim.lsp.start_client()| function lsp.client() error() end @@ -337,7 +355,7 @@ function lsp.start(config, opts) opts = opts or {} local reuse_client = opts.reuse_client or function(client, conf) - return client.config.root_dir == conf.root_dir and client.name == conf.name + return client.root_dir == conf.root_dir and client.name == conf.name end local bufnr = resolve_bufnr(opts.bufnr) @@ -537,20 +555,6 @@ local function on_client_exit(code, signal, client_id) end) end ---- @generic F: function ---- @param ... F ---- @return F -local function join_cbs(...) - local funcs = vim.F.pack_len(...) - return function(...) - for i = 1, funcs.n do - if funcs[i] ~= nil then - funcs[i](...) - end - end - end -end - -- FIXME: DOC: Currently all methods on the `vim.lsp.client` object are -- documented twice: Here, and on the methods themselves (e.g. -- `client.request()`). This is a workaround for the vimdoc generator script @@ -671,21 +675,22 @@ end --- fully initialized. Use `on_init` to do any actions once --- the client has been initialized. function lsp.start_client(config) - config = vim.deepcopy(config, false) - config.on_init = join_cbs(config.on_init, on_client_init) - config.on_exit = join_cbs(config.on_exit, on_client_exit) - - local client = require('vim.lsp.client').start(config) + local client = require('vim.lsp.client').create(config) if not client then return end + --- @diagnostic disable-next-line: invisible + table.insert(client._on_init_cbs, on_client_init) + --- @diagnostic disable-next-line: invisible + table.insert(client._on_exit_cbs, on_client_exit) + -- Store the uninitialized_clients for cleanup in case we exit before initialize finishes. - -- TODO(lewis6991): do this on before_init(). Requires API change to before_init() so it - -- can access the client_id. uninitialized_clients[client.id] = client + client:initialize() + return client.id end @@ -732,7 +737,7 @@ local function text_document_did_save_handler(bufnr) textDocument = { version = 0, uri = uri, - languageId = client.config.get_language_id(bufnr, vim.bo[bufnr].filetype), + languageId = client.get_language_id(bufnr, vim.bo[bufnr].filetype), text = lsp._buf_get_full_text(bufnr), }, }) @@ -1034,7 +1039,7 @@ api.nvim_create_autocmd('VimLeavePre', { local send_kill = false for client_id, client in pairs(active_clients) do - local timeout = if_nil(client.config.flags.exit_timeout, false) + local timeout = if_nil(client.flags.exit_timeout, false) if timeout then send_kill = true timeouts[client_id] = timeout diff --git a/runtime/lua/vim/lsp/_changetracking.lua b/runtime/lua/vim/lsp/_changetracking.lua index 8b624cd5ea..3ecdec1659 100644 --- a/runtime/lua/vim/lsp/_changetracking.lua +++ b/runtime/lua/vim/lsp/_changetracking.lua @@ -64,7 +64,7 @@ local state_by_group = setmetatable({}, { ---@param client lsp.Client ---@return vim.lsp.CTGroup local function get_group(client) - local allow_inc_sync = vim.F.if_nil(client.config.flags.allow_incremental_sync, true) --- @type boolean + local allow_inc_sync = vim.F.if_nil(client.flags.allow_incremental_sync, true) --- @type boolean local change_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'change') local sync_kind = change_capability or protocol.TextDocumentSyncKind.None if not allow_inc_sync and change_capability == protocol.TextDocumentSyncKind.Incremental then @@ -134,12 +134,12 @@ function M.init(client, bufnr) local group = get_group(client) local state = state_by_group[group] if state then - state.debounce = math.min(state.debounce, client.config.flags.debounce_text_changes or 150) + state.debounce = math.min(state.debounce, client.flags.debounce_text_changes or 150) state.clients[client.id] = client else state = { buffers = {}, - debounce = client.config.flags.debounce_text_changes or 150, + debounce = client.flags.debounce_text_changes or 150, clients = { [client.id] = client, }, diff --git a/runtime/lua/vim/lsp/_dynamic.lua b/runtime/lua/vim/lsp/_dynamic.lua index b6c335bb13..9c2af979fa 100644 --- a/runtime/lua/vim/lsp/_dynamic.lua +++ b/runtime/lua/vim/lsp/_dynamic.lua @@ -19,7 +19,7 @@ function M:supports_registration(method) if not client then return false end - local capability = vim.tbl_get(client.config.capabilities, unpack(vim.split(method, '/'))) + local capability = vim.tbl_get(client.capabilities, unpack(vim.split(method, '/'))) return type(capability) == 'table' and capability.dynamicRegistration end @@ -91,7 +91,7 @@ function M:match(bufnr, documentSelector) if not client then return false end - local language = client.config.get_language_id(bufnr, vim.bo[bufnr].filetype) + local language = client.get_language_id(bufnr, vim.bo[bufnr].filetype) local uri = vim.uri_from_bufnr(bufnr) local fname = vim.uri_to_fname(uri) for _, filter in ipairs(documentSelector) do diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua index 59b8c38166..6ca60b78cd 100644 --- a/runtime/lua/vim/lsp/_watchfiles.lua +++ b/runtime/lua/vim/lsp/_watchfiles.lua @@ -44,12 +44,8 @@ function M.register(reg, ctx) local client = assert(vim.lsp.get_client_by_id(client_id), 'Client must be running') -- Ill-behaved servers may not honor the client capability and try to register -- anyway, so ignore requests when the user has opted out of the feature. - local has_capability = vim.tbl_get( - client.config.capabilities or {}, - 'workspace', - 'didChangeWatchedFiles', - 'dynamicRegistration' - ) + local has_capability = + vim.tbl_get(client.capabilities, 'workspace', 'didChangeWatchedFiles', 'dynamicRegistration') if not has_capability or not client.workspace_folders then return end diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index a279be55e9..a460d95cc6 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -6,28 +6,33 @@ local ms = lsp.protocol.Methods local changetracking = lsp._changetracking local validate = vim.validate +--- @alias vim.lsp.client.on_init_cb fun(client: lsp.Client, initialize_result: lsp.InitializeResult) +--- @alias vim.lsp.client.on_attach_cb fun(client: lsp.Client, bufnr: integer) +--- @alias vim.lsp.client.on_exit_cb fun(code: integer, signal: integer, client_id: integer) +--- @alias vim.lsp.client.before_init_cb fun(params: lsp.InitializeParams, config: lsp.ClientConfig) + --- @class lsp.ClientConfig ---- @field cmd (string[]|fun(dispatchers: table):table) ---- @field cmd_cwd string ---- @field cmd_env (table) ---- @field detached boolean ---- @field workspace_folders (table) ---- @field capabilities lsp.ClientCapabilities ---- @field handlers table ---- @field settings table ---- @field commands table +--- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient? +--- @field cmd_cwd? string +--- @field cmd_env? table +--- @field detached? boolean +--- @field workspace_folders? lsp.WorkspaceFolder[] +--- @field capabilities? lsp.ClientCapabilities +--- @field handlers? table +--- @field settings? table +--- @field commands? table --- @field init_options table --- @field name? string ---- @field get_language_id fun(bufnr: integer, filetype: string): string ---- @field offset_encoding string ---- @field on_error fun(code: integer) ---- @field before_init fun(params: lsp.InitializeParams, config: lsp.ClientConfig) ---- @field on_init fun(client: lsp.Client, initialize_result: lsp.InitializeResult) ---- @field on_exit fun(code: integer, signal: integer, client_id: integer) ---- @field on_attach fun(client: lsp.Client, bufnr: integer) ---- @field trace 'off'|'messages'|'verbose'|nil ---- @field flags table ---- @field root_dir string +--- @field get_language_id? fun(bufnr: integer, filetype: string): string +--- @field offset_encoding? string +--- @field on_error? fun(code: integer, err: string) +--- @field before_init? vim.lsp.client.before_init_cb +--- @field on_init? elem_or_list +--- @field on_exit? elem_or_list +--- @field on_attach? elem_or_list +--- @field trace? 'off'|'messages'|'verbose' +--- @field flags? table +--- @field root_dir? string --- @class lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}> --- @field pending table @@ -66,21 +71,43 @@ local validate = vim.validate --- --- Response from the server sent on --- initialize` describing the server's capabilities. ---- @field server_capabilities lsp.ServerCapabilities +--- @field server_capabilities lsp.ServerCapabilities? --- --- A ring buffer (|vim.ringbuf()|) containing progress messages --- sent by the server. --- @field progress lsp.Client.Progress --- --- @field initialized true? +--- +--- The workspace folders configured in the client when the server starts. +--- This property is only available if the client supports workspace folders. +--- It can be `null` if the client supports workspace folders but none are +--- configured. --- @field workspace_folders lsp.WorkspaceFolder[]? +--- @field root_dir string +--- --- @field attached_buffers table --- @field private _log_prefix string +--- --- Track this so that we can escalate automatically if we've already tried a --- graceful shutdown --- @field private _graceful_shutdown_failed true? ---- @field private commands table --- +--- The initial trace setting. If omitted trace is disabled ("off"). +--- trace = "off" | "messages" | "verbose"; +--- @field private _trace 'off'|'messages'|'verbose' +--- +--- Table of command name to function which is called if any LSP action +--- (code action, code lenses, ...) triggers the command. +--- Client commands take precedence over the global command registry. +--- @field commands table +--- +--- @field settings table +--- @field flags table +--- @field get_language_id fun(bufnr: integer, filetype: string): string +--- +--- The capabilities provided by the client (editor or tool) +--- @field capabilities lsp.ClientCapabilities --- @field dynamic_capabilities lsp.DynamicCapabilities --- --- Sends a request to the server. @@ -122,6 +149,12 @@ local validate = vim.validate --- Useful for buffer-local setup. --- @field on_attach fun(bufnr: integer) --- +--- @field private _before_init_cb? vim.lsp.client.before_init_cb +--- @field private _on_attach_cbs vim.lsp.client.on_attach_cb[] +--- @field private _on_init_cbs vim.lsp.client.on_init_cb[] +--- @field private _on_exit_cbs vim.lsp.client.on_exit_cb[] +--- @field private _on_error_cb? fun(code: integer, err: string) +--- --- Checks if a client supports a given method. --- Always returns true for unknown off-spec methods. --- [opts] is a optional `{bufnr?: integer}` table. @@ -196,9 +229,18 @@ local function optional_validator(fn) end end +--- By default, get_language_id just returns the exact filetype it is passed. +--- It is possible to pass in something that will calculate a different filetype, +--- to be sent by the client. +--- @param _bufnr integer +--- @param filetype string +local function default_get_language_id(_bufnr, filetype) + return filetype +end + --- Validates a client configuration as given to |vim.lsp.start_client()|. --- @param config lsp.ClientConfig -local function process_client_config(config) +local function validate_config(config) validate({ config = { config, 't' }, }) @@ -210,15 +252,17 @@ local function process_client_config(config) detached = { config.detached, 'b', true }, name = { config.name, 's', true }, on_error = { config.on_error, 'f', true }, - on_exit = { config.on_exit, 'f', true }, - on_init = { config.on_init, 'f', true }, + on_exit = { config.on_exit, { 'f', 't' }, true }, + on_init = { config.on_init, { 'f', 't' }, true }, + on_attach = { config.on_attach, { 'f', 't' }, true }, settings = { config.settings, 't', true }, commands = { config.commands, 't', true }, - before_init = { config.before_init, 'f', true }, + before_init = { config.before_init, { 'f', 't' }, true }, offset_encoding = { config.offset_encoding, 's', true }, flags = { config.flags, 't', true }, get_language_id = { config.get_language_id, 'f', true }, }) + assert( ( not config.flags @@ -227,51 +271,98 @@ local function process_client_config(config) ), 'flags.debounce_text_changes must be a number with the debounce time in milliseconds' ) +end + +--- @param trace string +--- @return 'off'|'messages'|'verbose' +local function get_trace(trace) + local valid_traces = { + off = 'off', + messages = 'messages', + verbose = 'verbose', + } + return trace and valid_traces[trace] or 'off' +end - if not config.name and type(config.cmd) == 'table' then - config.name = config.cmd[1] and vim.fs.basename(config.cmd[1]) or nil +--- @param id integer +--- @param config lsp.ClientConfig +--- @return string +local function get_name(id, config) + local name = config.name + if name then + return name end - config.offset_encoding = validate_encoding(config.offset_encoding) - config.flags = config.flags or {} - config.settings = config.settings or {} - config.handlers = config.handlers or {} + if type(config.cmd) == 'table' and config.cmd[1] then + return assert(vim.fs.basename(config.cmd[1])) + end - -- By default, get_language_id just returns the exact filetype it is passed. - -- It is possible to pass in something that will calculate a different filetype, - -- to be sent by the client. - config.get_language_id = config.get_language_id or function(_, filetype) - return filetype + return tostring(id) +end + +--- @param workspace_folders lsp.WorkspaceFolder[]? +--- @param root_dir string? +--- @return lsp.WorkspaceFolder[]? +local function get_workspace_folders(workspace_folders, root_dir) + if workspace_folders then + return workspace_folders end + if root_dir then + return { + { + uri = vim.uri_from_fname(root_dir), + name = string.format('%s', root_dir), + }, + } + end +end - config.capabilities = config.capabilities or lsp.protocol.make_client_capabilities() - config.commands = config.commands or {} +--- @generic T +--- @param x elem_or_list? +--- @return T[] +local function ensure_list(x) + if type(x) == 'table' then + return x + end + return { x } end --- @package --- @param config lsp.ClientConfig --- @return lsp.Client? -function Client.start(config) - process_client_config(config) +function Client.create(config) + validate_config(config) client_index = client_index + 1 local id = client_index - - local name = config.name or tostring(id) + local name = get_name(id, config) --- @class lsp.Client local self = { id = id, config = config, - handlers = config.handlers, - offset_encoding = config.offset_encoding, + handlers = config.handlers or {}, + offset_encoding = validate_encoding(config.offset_encoding), name = name, _log_prefix = string.format('LSP[%s]', name), requests = {}, attached_buffers = {}, server_capabilities = {}, - dynamic_capabilities = vim.lsp._dynamic.new(id), - commands = config.commands, -- Remove in Nvim 0.11 + dynamic_capabilities = lsp._dynamic.new(id), + commands = config.commands or {}, + settings = config.settings or {}, + flags = config.flags or {}, + get_language_id = config.get_language_id or default_get_language_id, + capabilities = config.capabilities or lsp.protocol.make_client_capabilities(), + workspace_folders = get_workspace_folders(config.workspace_folders, config.root_dir), + root_dir = config.root_dir, + _before_init_cb = config.before_init, + _on_init_cbs = ensure_list(config.on_init), + _on_exit_cbs = ensure_list(config.on_exit), + _on_attach_cbs = ensure_list(config.on_attach), + _on_error_cb = config.on_error, + _root_dir = config.root_dir, + _trace = get_trace(config.trace), --- Contains $/progress report messages. --- They have the format {token: integer|string, value: any} @@ -327,41 +418,31 @@ function Client.start(config) setmetatable(self, Client) - self:initialize() - return self end ---- @private -function Client:initialize() - local valid_traces = { - off = 'off', - messages = 'messages', - verbose = 'verbose', - } +--- @param cbs function[] +--- @param error_id integer +--- @param ... any +function Client:_run_callbacks(cbs, error_id, ...) + for _, cb in pairs(cbs) do + --- @type boolean, string? + local status, err = pcall(cb, ...) + if not status then + self:write_error(error_id, err) + end + end +end +--- @package +function Client:initialize() local config = self.config - local workspace_folders --- @type lsp.WorkspaceFolder[]? local root_uri --- @type string? local root_path --- @type string? - if config.workspace_folders or config.root_dir then - if config.root_dir and not config.workspace_folders then - workspace_folders = { - { - uri = vim.uri_from_fname(config.root_dir), - name = string.format('%s', config.root_dir), - }, - } - else - workspace_folders = config.workspace_folders - end - root_uri = workspace_folders[1].uri + if self.workspace_folders then + root_uri = self.workspace_folders[1].uri root_path = vim.uri_to_fname(root_uri) - else - workspace_folders = nil - root_uri = nil - root_path = nil end local initialize_params = { @@ -383,26 +464,19 @@ function Client:initialize() -- The rootUri of the workspace. Is null if no folder is open. If both -- `rootPath` and `rootUri` are set `rootUri` wins. rootUri = root_uri or vim.NIL, - -- The workspace folders configured in the client when the server starts. - -- This property is only available if the client supports workspace folders. - -- It can be `null` if the client supports workspace folders but none are - -- configured. - workspaceFolders = workspace_folders or vim.NIL, + workspaceFolders = self.workspace_folders or vim.NIL, -- User provided initialization options. initializationOptions = config.init_options, - -- The capabilities provided by the client (editor or tool) - capabilities = config.capabilities, - -- The initial trace setting. If omitted trace is disabled ("off"). - -- trace = "off" | "messages" | "verbose"; - trace = valid_traces[config.trace] or 'off', + capabilities = self.capabilities, + trace = self._trace, } - if config.before_init then - --- @type boolean, string? - local status, err = pcall(config.before_init, initialize_params, config) - if not status then - self:write_error(lsp.client_errors.BEFORE_INIT_CALLBACK_ERROR, err) - end - end + + self:_run_callbacks( + { self._before_init_cb }, + lsp.client_errors.BEFORE_INIT_CALLBACK_ERROR, + initialize_params, + config + ) log.trace(self._log_prefix, 'initialize_params', initialize_params) @@ -413,7 +487,6 @@ function Client:initialize() assert(result, 'server sent empty result') rpc.notify('initialized', vim.empty_dict()) self.initialized = true - self.workspace_folders = workspace_folders -- These are the cleaned up capabilities we use for dynamically deciding -- when to send certain events to clients. @@ -425,17 +498,11 @@ function Client:initialize() self.offset_encoding = self.server_capabilities.positionEncoding end - if next(config.settings) then - self:_notify(ms.workspace_didChangeConfiguration, { settings = config.settings }) + if next(self.settings) then + self:_notify(ms.workspace_didChangeConfiguration, { settings = self.settings }) end - if config.on_init then - --- @type boolean, string? - local status, err = pcall(config.on_init, self, result) - if not status then - self:write_error(lsp.client_errors.ON_INIT_CALLBACK_ERROR, err) - end - end + self:_run_callbacks(self._on_init_cbs, lsp.client_errors.ON_INIT_CALLBACK_ERROR, self, result) log.info( self._log_prefix, @@ -672,7 +739,7 @@ function Client:_is_stopped() return self.rpc.is_closing() end ---- @private +--- @package --- Execute a lsp command, either via client command function (if available) --- or via workspace/executeCommand (if supported by the server) --- @@ -684,7 +751,7 @@ function Client:_exec_cmd(command, context, handler) context.bufnr = context.bufnr or api.nvim_get_current_buf() context.client_id = self.id local cmdname = command.command - local fn = self.config.commands[cmdname] or lsp.commands[cmdname] + local fn = self.commands[cmdname] or lsp.commands[cmdname] if fn then fn(command, context) return @@ -730,7 +797,7 @@ function Client:_text_document_did_open_handler(bufnr) textDocument = { version = 0, uri = vim.uri_from_bufnr(bufnr), - languageId = self.config.get_language_id(bufnr, filetype), + languageId = self.get_language_id(bufnr, filetype), text = lsp._buf_get_full_text(bufnr), }, } @@ -742,13 +809,13 @@ function Client:_text_document_did_open_handler(bufnr) -- Protect against a race where the buffer disappears -- between `did_open_handler` and the scheduled function firing. if api.nvim_buf_is_valid(bufnr) then - local namespace = vim.lsp.diagnostic.get_namespace(self.id) + local namespace = lsp.diagnostic.get_namespace(self.id) vim.diagnostic.show(namespace, bufnr) end end) end ---- @private +--- @package --- Runs the on_attach function from the client's config if it was defined. --- @param bufnr integer Buffer number function Client:_on_attach(bufnr) @@ -762,13 +829,7 @@ function Client:_on_attach(bufnr) data = { client_id = self.id }, }) - if self.config.on_attach then - --- @type boolean, string? - local status, err = pcall(self.config.on_attach, self, bufnr) - if not status then - self:write_error(lsp.client_errors.ON_ATTACH_ERROR, err) - end - end + self:_run_callbacks(self._on_attach_cbs, lsp.client_errors.ON_ATTACH_ERROR, self, bufnr) -- schedule the initialization of semantic tokens to give the above -- on_attach and LspAttach callbacks the ability to schedule wrap the @@ -795,7 +856,6 @@ end --- @param method string --- @param opts? {bufnr: integer?} function Client:_supports_method(method, opts) - opts = opts or {} local required_capability = lsp._request_name_to_capability[method] -- if we don't know about the method, assume that the client supports it. if not required_capability then @@ -803,12 +863,11 @@ function Client:_supports_method(method, opts) end if vim.tbl_get(self.server_capabilities, unpack(required_capability)) then return true - else - if self.dynamic_capabilities:supports_registration(method) then - return self.dynamic_capabilities:supports(method, opts) - end - return false end + if self.dynamic_capabilities:supports_registration(method) then + return self.dynamic_capabilities:supports(method, opts) + end + return false end --- @private @@ -853,9 +912,9 @@ end --- `vim.lsp.rpc.client_errors[code]` to get a human-friendly name. function Client:_on_error(code, err) self:write_error(code, err) - if self.config.on_error then + if self._on_error_cb then --- @type boolean, string - local status, usererr = pcall(self.config.on_error, code, err) + local status, usererr = pcall(self._on_error_cb, code, err) if not status then log.error(self._log_prefix, 'user on_error failed', { err = usererr }) err_message(self._log_prefix, ' user on_error failed: ', tostring(usererr)) @@ -869,9 +928,13 @@ end --- @param code integer) exit code of the process --- @param signal integer the signal used to terminate (if any) function Client:_on_exit(code, signal) - if self.config.on_exit then - pcall(self.config.on_exit, code, signal, self.id) - end + self:_run_callbacks( + self._on_exit_cbs, + lsp.client_errors.ON_EXIT_CALLBACK_ERROR, + code, + signal, + self.id + ) end return Client diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index ab49e03c52..966c7f4d03 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -48,7 +48,6 @@ local function execute_lens(lens, bufnr, client_id) local client = vim.lsp.get_client_by_id(client_id) assert(client, 'Client is required to execute lens, client_id=' .. client_id) - ---@diagnostic disable-next-line: invisible client:_exec_cmd(lens.command, { bufnr = bufnr }, function(...) vim.lsp.handlers[ms.workspace_executeCommand](...) M.refresh() diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 4bb14e5a09..a9da812231 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -197,10 +197,10 @@ M[ms.workspace_configuration] = function(_, result, ctx) local response = {} for _, item in ipairs(result.items) do if item.section then - local value = lookup_section(client.config.settings, item.section) + local value = lookup_section(client.settings, item.section) -- For empty sections with no explicit '' key, return settings as is if value == nil and item.section == '' then - value = client.config.settings + value = client.settings end if value == nil then value = vim.NIL diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua index d770735895..15e4555b55 100644 --- a/runtime/lua/vim/lsp/health.lua +++ b/runtime/lua/vim/lsp/health.lua @@ -38,7 +38,7 @@ function M.check() '%s (id=%s, root_dir=%s, attached_to=[%s])', client.name, client.id, - vim.fn.fnamemodify(client.config.root_dir, ':~'), + vim.fn.fnamemodify(client.root_dir, ':~'), attached_to ) ) -- cgit From d09957e0a06f350443c750d9838b5f1016c0cccc Mon Sep 17 00:00:00 2001 From: Tomasz N Date: Wed, 14 Feb 2024 21:11:29 +0100 Subject: fix(lsp): rename: load and list new buffer if attached to window (#27408) --- runtime/lua/vim/lsp/util.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 86bef1ac8a..4abc58ee3c 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -702,6 +702,8 @@ function M.rename(old_fname, new_fname, opts) if vim.fn.isdirectory(new_fname) == 0 then local newbuf = vim.fn.bufadd(new_fname) if win then + vim.fn.bufload(newbuf) + vim.bo[newbuf].buflisted = true api.nvim_win_set_buf(win, newbuf) end end -- cgit From 4f07ad77869b30ecf7b7b7ed9b53ffcda908c94b Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Thu, 15 Feb 2024 00:09:00 +0100 Subject: vim-patch:9.1.0108: filetype: no support for dtso files Problem: filetype: no support for dtso files Solution: Add detection for *.dtso files as dts file type (Markus Schneider-Pargmann) *.dtso files are devicetree overlay files which have the same syntax as dts or dtsi files. closes: vim/vim#14026 https://github.com/vim/vim/commit/b1700fb33fe02838d679b9215e501455cf4c1156 Co-authored-by: Markus Schneider-Pargmann --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 7fa92d1664..e73d139d02 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -364,6 +364,7 @@ local extension = { d = detect.dtrace, dts = 'dts', dtsi = 'dts', + dtso = 'dts', dylan = 'dylan', intr = 'dylanintr', lid = 'dylanlid', -- cgit From 7ed75d410a23f3fbf0e509433ce8bee32fd63963 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Thu, 15 Feb 2024 00:10:03 +0100 Subject: vim-patch:9.1.0109: filetype: no support for its files Problem: filetype: no support for its files Solution: Add detection for *.its files as dts file type (Brandon Maier) The '*.its' file type is for U-Boot Flattened Image Trees (FIT) which use the flattened devicetree format. See https://github.com/u-boot/u-boot/blob/master/doc/usage/fit/source_file_format.rst#terminology closes: vim/vim#14037 https://github.com/vim/vim/commit/cf1d65e060e32ba8a0ba99fc299dc192fe4aa961 Co-authored-by: Brandon Maier --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index e73d139d02..65f07f02d1 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -365,6 +365,7 @@ local extension = { dts = 'dts', dtsi = 'dts', dtso = 'dts', + its = 'dts', dylan = 'dylan', intr = 'dylanintr', lid = 'dylanlid', -- cgit From d0599b0ed9ff77f1286f2302f92dd4e96cc98a5b Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Thu, 15 Feb 2024 00:10:53 +0100 Subject: vim-patch:9.1.0110: filetype: add 'Config.in' filetype detection The 'Config.in' file type is for Buildroot configuration files. Buildroot Config.in files use the same Kconfig backend as the Linux kernel's Kconfig files. Buildroot also has other filename variants that follow "Config.in.*", they are used to distinguish multiple Config.in files in the same directory. See https://buildroot.org/downloads/manual/manual.html#_literal_config_in_literal_file closes: vim/vim#14038 https://github.com/vim/vim/commit/5f20f050efed3431beaf85739f0113e9ef0abd8e Co-authored-by: Brandon Maier --- runtime/lua/vim/filetype.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 65f07f02d1..518ef13e6f 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1348,6 +1348,7 @@ local filename = { ['.justfile'] = 'just', Kconfig = 'kconfig', ['Kconfig.debug'] = 'kconfig', + ['Config.in'] = 'kconfig', ['lftp.conf'] = 'lftp', ['.lftprc'] = 'lftp', ['/.libao'] = 'libao', @@ -1739,6 +1740,7 @@ local pattern = { ['[jt]sconfig.*%.json'] = 'jsonc', ['[jJ]ustfile'] = 'just', ['Kconfig%..*'] = starsetf('kconfig'), + ['Config%.in%..*'] = starsetf('kconfig'), ['.*%.[Ss][Uu][Bb]'] = 'krl', ['lilo%.conf.*'] = starsetf('lilo'), ['.*/etc/logcheck/.*%.d.*/.*'] = starsetf('logcheck'), -- cgit From 0a51e7626a95a068c7bb00d0da28a701fed758da Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Thu, 15 Feb 2024 00:35:54 +0100 Subject: vim-patch:9.1.0111: filetype: no support for bats files The '*.bats' file type is for Bash Automated Testing System (BATS) scripts. BATS scripts are Bash with a special '@test' extension but they otherwise work with Vim's bash filetype. See https://github.com/bats-core/bats-core closes: vim/vim#14039 https://github.com/vim/vim/commit/d00fb4b3a237b375de5a1f453c8453b8b3797d51 Co-authored-by: Brandon Maier --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 518ef13e6f..b43072a725 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -910,6 +910,7 @@ local extension = { sed = 'sed', sexp = 'sexplib', bash = detect.bash, + bats = detect.bash, ebuild = detect.bash, eclass = detect.bash, env = detect.sh, -- cgit From 35f453f65df2cab4eaeda99c205d1fda235b7bc9 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 15 Feb 2024 10:53:51 +0000 Subject: fix: type warnings in shared.lua --- runtime/lua/vim/_init_packages.lua | 1 + runtime/lua/vim/_meta/builtin.lua | 1 + runtime/lua/vim/_meta/misc.lua | 3 +- runtime/lua/vim/shared.lua | 85 +++++++++++++++++++++++++++++--------- 4 files changed, 69 insertions(+), 21 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_init_packages.lua b/runtime/lua/vim/_init_packages.lua index 83ef4efb9f..71ac3bcfcd 100644 --- a/runtime/lua/vim/_init_packages.lua +++ b/runtime/lua/vim/_init_packages.lua @@ -86,6 +86,7 @@ setmetatable(vim, { --- ---@private --- TODO: should be in vim.shared when vim.shared always uses nvim-lua +--- @diagnostic disable-next-line:duplicate-set-field function vim.empty_dict() return setmetatable({}, vim._empty_dict_mt) end diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua index dd849e5247..a422a65792 100644 --- a/runtime/lua/vim/_meta/builtin.lua +++ b/runtime/lua/vim/_meta/builtin.lua @@ -83,6 +83,7 @@ function vim.in_fast_event() end --- --- Note: If numeric keys are present in the table, Nvim ignores the metatable --- marker and converts the dict to a list/array anyway. +--- @return table function vim.empty_dict() end --- Sends {event} to {channel} via |RPC| and returns immediately. If {channel} diff --git a/runtime/lua/vim/_meta/misc.lua b/runtime/lua/vim/_meta/misc.lua index 0d70e16314..ab80e18434 100644 --- a/runtime/lua/vim/_meta/misc.lua +++ b/runtime/lua/vim/_meta/misc.lua @@ -10,6 +10,7 @@ --- vim.fn[func]({...}) --- ``` --- ---- @param func fun() +--- @param func string --- @param ... any +--- @return any function vim.call(func, ...) end diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index dd0f7c2e1e..5cf8390843 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -63,6 +63,10 @@ function vim.deepcopy(orig, noref) return deepcopy(orig, not noref and {} or nil) end +--- @class vim.gsplit.Opts +--- @field plain? boolean Use `sep` literally (as in string.find). +--- @field trimempty? boolean Discard empty segments at start and end of the sequence. + --- Gets an |iterator| that splits a string at each instance of a separator, in "lazy" fashion --- (as opposed to |vim.split()| which is "eager"). --- @@ -91,12 +95,12 @@ end --- --- @param s string String to split --- @param sep string Separator or pattern ---- @param opts (table|nil) Keyword arguments |kwargs|: +--- @param opts? vim.gsplit.Opts (table) Keyword arguments |kwargs|: --- - plain: (boolean) Use `sep` literally (as in string.find). --- - trimempty: (boolean) Discard empty segments at start and end of the sequence. ---@return fun():string|nil (function) Iterator over the split components function vim.gsplit(s, sep, opts) - local plain + local plain --- @type boolean? local trimempty = false if type(opts) == 'boolean' then plain = opts -- For backwards compatibility. @@ -113,6 +117,11 @@ function vim.gsplit(s, sep, opts) local segs = {} local empty_start = true -- Only empty segments seen so far. + --- @param i integer? + --- @param j integer + --- @param ... unknown + --- @return string + --- @return ... local function _pass(i, j, ...) if i then assert(j + 1 > start, 'Infinite loop detected') @@ -201,10 +210,11 @@ end ---@param t table (table) Table ---@return T[] (list) List of keys function vim.tbl_keys(t) - assert(type(t) == 'table', string.format('Expected table, got %s', type(t))) + vim.validate({ t = { t, 't' } }) + --- @cast t table local keys = {} - for k, _ in pairs(t) do + for k in pairs(t) do table.insert(keys, k) end return keys @@ -217,10 +227,12 @@ end ---@param t table (table) Table ---@return T[] (list) List of values function vim.tbl_values(t) - assert(type(t) == 'table', string.format('Expected table, got %s', type(t))) + vim.validate({ t = { t, 't' } }) local values = {} - for _, v in pairs(t) do + for _, v in + pairs(t --[[@as table]]) + do table.insert(values, v) end return values @@ -234,8 +246,9 @@ end ---@return table Table of transformed values function vim.tbl_map(func, t) vim.validate({ func = { func, 'c' }, t = { t, 't' } }) + --- @cast t table - local rettab = {} + local rettab = {} --- @type table for k, v in pairs(t) do rettab[k] = func(v) end @@ -250,16 +263,20 @@ end ---@return T[] (table) Table of filtered values function vim.tbl_filter(func, t) vim.validate({ func = { func, 'c' }, t = { t, 't' } }) + --- @cast t table - local rettab = {} + local rettab = {} --- @type table for _, entry in pairs(t) do if func(entry) then - table.insert(rettab, entry) + rettab[#rettab + 1] = entry end end return rettab end +--- @class vim.tbl_contains.Opts +--- @field predicate? boolean + --- Checks if a table contains a given value, specified either directly or via --- a predicate that is checked for each value. --- @@ -276,13 +293,14 @@ end --- ---@param t table Table to check ---@param value any Value to compare or predicate function reference ----@param opts (table|nil) Keyword arguments |kwargs|: +---@param opts? vim.tbl_contains.Opts (table) Keyword arguments |kwargs|: --- - predicate: (boolean) `value` is a function reference to be checked (default false) ---@return boolean `true` if `t` contains `value` function vim.tbl_contains(t, value, opts) vim.validate({ t = { t, 't' }, opts = { opts, 't', true } }) + --- @cast t table - local pred + local pred --- @type fun(v: any): boolean? if opts and opts.predicate then vim.validate({ value = { value, 'c' } }) pred = value @@ -309,6 +327,7 @@ end ---@return boolean `true` if `t` contains `value` function vim.list_contains(t, value) vim.validate({ t = { t, 't' } }) + --- @cast t table for _, v in ipairs(t) do if v == value then @@ -325,7 +344,7 @@ end ---@param t table Table to check ---@return boolean `true` if `t` is empty function vim.tbl_isempty(t) - assert(type(t) == 'table', string.format('Expected table, got %s', type(t))) + vim.validate({ t = { t, 't' } }) return next(t) == nil end @@ -347,7 +366,7 @@ local function tbl_extend(behavior, deep_extend, ...) ) end - local ret = {} + local ret = {} --- @type table if vim._empty_dict_mt ~= nil and getmetatable(select(1, ...)) == vim._empty_dict_mt then ret = vim.empty_dict() end @@ -355,6 +374,7 @@ local function tbl_extend(behavior, deep_extend, ...) for i = 1, select('#', ...) do local tbl = select(i, ...) vim.validate({ ['after the second argument'] = { tbl, 't' } }) + --- @cast tbl table if tbl then for k, v in pairs(tbl) do if deep_extend and can_merge(v) and can_merge(ret[k]) then @@ -417,12 +437,14 @@ function vim.deep_equal(a, b) return false end if type(a) == 'table' then + --- @cast a table + --- @cast b table for k, v in pairs(a) do if not vim.deep_equal(v, b[k]) then return false end end - for k, _ in pairs(b) do + for k in pairs(b) do if a[k] == nil then return false end @@ -440,6 +462,8 @@ end ---@param o table Table to add the reverse to ---@return table o function vim.tbl_add_reverse_lookup(o) + --- @cast o table + --- @type any[] local keys = vim.tbl_keys(o) for _, k in ipairs(keys) do local v = o[k] @@ -469,7 +493,6 @@ end --- ---@param o table Table to index ---@param ... any Optional keys (0 or more, variadic) via which to index the table ---- ---@return any Nested value indexed by key (if it exists), else nil function vim.tbl_get(o, ...) local keys = { ... } @@ -477,7 +500,7 @@ function vim.tbl_get(o, ...) return nil end for i, k in ipairs(keys) do - o = o[k] + o = o[k] --- @type any if o == nil then return nil elseif type(o) ~= 'table' and next(keys, i) then @@ -521,6 +544,7 @@ end ---@return table Flattened copy of the given list-like table function vim.tbl_flatten(t) local result = {} + --- @param _t table local function _tbl_flatten(_t) local n = #_t for i = 1, n do @@ -543,7 +567,8 @@ end ---@param t table Dict-like table ---@return function # |for-in| iterator over sorted keys and their values function vim.spairs(t) - assert(type(t) == 'table', string.format('Expected table, got %s', type(t))) + vim.validate({ t = { t, 't' } }) + --- @cast t table -- collect the keys local keys = {} @@ -578,6 +603,8 @@ function vim.tbl_isarray(t) return false end + --- @cast t table + local count = 0 for k, _ in pairs(t) do @@ -642,6 +669,7 @@ end ---@return integer Number of non-nil values in table function vim.tbl_count(t) vim.validate({ t = { t, 't' } }) + --- @cast t table local count = 0 for _ in pairs(t) do @@ -658,7 +686,7 @@ end ---@param finish integer|nil End range of slice ---@return T[] (list) Copy of table sliced from start to finish (inclusive) function vim.list_slice(list, start, finish) - local new_list = {} + local new_list = {} --- @type `T`[] for i = start or 1, finish or #list do new_list[#new_list + 1] = list[i] end @@ -707,6 +735,16 @@ function vim.endswith(s, suffix) end do + --- @alias vim.validate.Type + --- | 't' | 'table' + --- | 's' | 'string' + --- | 'n' | 'number' + --- | 'f' | 'function' + --- | 'c' | 'callable' + --- | 'nil' + --- | 'thread' + --- | 'userdata + local type_names = { ['table'] = 'table', t = 'table', @@ -725,10 +763,17 @@ do ['userdata'] = 'userdata', } + --- @class vim.validate.Spec {[1]: any, [2]: string|string[], [3]: boolean } + --- @field [1] any Argument value + --- @field [2] string|string[]|fun(v:any):boolean, string? Type name, or callable + --- @field [3]? boolean + local function _is_type(val, t) return type(val) == t or (t == 'callable' and vim.is_callable(val)) end + --- @param opt table + --- @return boolean, string? local function is_valid(opt) if type(opt) ~= 'table' then return false, string.format('opt: expected table, got %s', type(opt)) @@ -787,7 +832,7 @@ do end end - return true, nil + return true end --- Validates a parameter specification (types and values). @@ -829,7 +874,7 @@ do --- --- ``` --- - ---@param opt table Names of parameters to validate. Each key is a parameter + ---@param opt table (table) Names of parameters to validate. Each key is a parameter --- name; each value is a tuple in one of these forms: --- 1. (arg_value, type_name, optional) --- - arg_value: argument value -- cgit From 55a4aa41bb27aa9439fea11c4ebcfec2ee87844d Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Thu, 15 Feb 2024 19:56:58 -0600 Subject: docs: document breaking change for nvim_create_autocmd callback (#27484) https://github.com/neovim/neovim/pull/27428 changed the semantics of callbacks passed to nvim_create_autocmd such that any truthy value will delete the autocommand (rather than just the literal boolean value `true`). Update the documentation accordingly and add an entry to `news.txt`. The behavior is now consistent between nvim_create_autocmd and nvim_buf_attach. --- runtime/lua/vim/_meta/api.lua | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index f46ab8023f..0978f0acf5 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -155,8 +155,9 @@ function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start --- will be `nvim_buf_changedtick_event`. Not for Lua --- callbacks. --- @param opts vim.api.keyset.buf_attach Optional parameters. ---- • on_lines: Lua callback invoked on change. Return `true` to ---- detach. Args: +--- • on_lines: Lua callback invoked on change. Return a +--- truthy value (not `false` or `nil`) +--- to detach. Args: --- • the string "lines" --- • buffer handle --- • b:changedtick @@ -169,7 +170,8 @@ function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start --- --- • on_bytes: Lua callback invoked on change. This --- callback receives more granular information about the ---- change compared to on_lines. Return `true` to +--- change compared to on_lines. Return a truthy value +--- (not `false` or `nil`) to --- detach. Args: --- • the string "bytes" --- • buffer handle @@ -863,9 +865,9 @@ function vim.api.nvim_create_augroup(name, opts) end --- troubleshooting). --- • callback (function|string) optional: Lua function (or --- Vimscript function name, if string) called when the ---- event(s) is triggered. Lua callback can return true to ---- delete the autocommand, and receives a table argument with ---- these keys: +--- event(s) is triggered. Lua callback can return a truthy +--- value (not `false` or `nil`) to delete the +--- autocommand. Receives a table argument with these keys: --- • id: (number) autocommand id --- • event: (string) name of the triggered event --- `autocmd-events` -- cgit From bd5008de07d29a6457ddc7fe13f9f85c9c4619d2 Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Fri, 16 Feb 2024 18:54:47 +0100 Subject: fix(treesitter): correctly handle query quantifiers (#24738) Query patterns can contain quantifiers (e.g. (foo)+ @bar), so a single capture can map to multiple nodes. The iter_matches API can not handle this situation because the match table incorrectly maps capture indices to a single node instead of to an array of nodes. The match table should be updated to map capture indices to an array of nodes. However, this is a massively breaking change, so must be done with a proper deprecation period. `iter_matches`, `add_predicate` and `add_directive` must opt-in to the correct behavior for backward compatibility. This is done with a new "all" option. This option will become the default and removed after the 0.10 release. Co-authored-by: Christian Clason Co-authored-by: MDeiml Co-authored-by: Gregory Anders --- runtime/lua/vim/treesitter/_meta.lua | 4 +- runtime/lua/vim/treesitter/_query_linter.lua | 28 +- runtime/lua/vim/treesitter/languagetree.lua | 28 +- runtime/lua/vim/treesitter/query.lua | 422 +++++++++++++++++++-------- 4 files changed, 335 insertions(+), 147 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/_meta.lua b/runtime/lua/vim/treesitter/_meta.lua index 6a714de052..0b285d2d7f 100644 --- a/runtime/lua/vim/treesitter/_meta.lua +++ b/runtime/lua/vim/treesitter/_meta.lua @@ -39,7 +39,7 @@ local TSNode = {} ---@param start? integer ---@param end_? integer ---@param opts? table ----@return fun(): integer, TSNode, any +---@return fun(): integer, TSNode, TSMatch function TSNode:_rawquery(query, captures, start, end_, opts) end ---@param query TSQuery @@ -47,7 +47,7 @@ function TSNode:_rawquery(query, captures, start, end_, opts) end ---@param start? integer ---@param end_? integer ---@param opts? table ----@return fun(): integer, any +---@return fun(): integer, TSMatch function TSNode:_rawquery(query, captures, start, end_, opts) end ---@alias TSLoggerCallback fun(logtype: 'parse'|'lex', msg: string) diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua index 8651e187c2..378e9c67aa 100644 --- a/runtime/lua/vim/treesitter/_query_linter.lua +++ b/runtime/lua/vim/treesitter/_query_linter.lua @@ -122,7 +122,7 @@ local parse = vim.func._memoize(hash_parse, function(node, buf, lang) end) --- @param buf integer ---- @param match table +--- @param match table --- @param query Query --- @param lang_context QueryLinterLanguageContext --- @param diagnostics Diagnostic[] @@ -130,20 +130,22 @@ local function lint_match(buf, match, query, lang_context, diagnostics) local lang = lang_context.lang local parser_info = lang_context.parser_info - for id, node in pairs(match) do - local cap_id = query.captures[id] + for id, nodes in pairs(match) do + for _, node in ipairs(nodes) do + local cap_id = query.captures[id] - -- perform language-independent checks only for first lang - if lang_context.is_first_lang and cap_id == 'error' then - local node_text = vim.treesitter.get_node_text(node, buf):gsub('\n', ' ') - add_lint_for_node(diagnostics, { node:range() }, 'Syntax error: ' .. node_text) - end + -- perform language-independent checks only for first lang + if lang_context.is_first_lang and cap_id == 'error' then + local node_text = vim.treesitter.get_node_text(node, buf):gsub('\n', ' ') + add_lint_for_node(diagnostics, { node:range() }, 'Syntax error: ' .. node_text) + end - -- other checks rely on Neovim parser introspection - if lang and parser_info and cap_id == 'toplevel' then - local err = parse(node, buf, lang) - if err then - add_lint_for_node(diagnostics, err.range, err.msg, lang) + -- other checks rely on Neovim parser introspection + if lang and parser_info and cap_id == 'toplevel' then + local err = parse(node, buf, lang) + if err then + add_lint_for_node(diagnostics, err.range, err.msg, lang) + end end end end diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 971c4449e8..79566f5eeb 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -784,7 +784,7 @@ end ---@private --- Extract injections according to: --- https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection ----@param match table +---@param match table ---@param metadata TSMetadata ---@return string?, boolean, Range6[] function LanguageTree:_get_injection(match, metadata) @@ -796,14 +796,16 @@ function LanguageTree:_get_injection(match, metadata) or (injection_lang and resolve_lang(injection_lang)) local include_children = metadata['injection.include-children'] ~= nil - for id, node in pairs(match) do - local name = self._injection_query.captures[id] - -- Lang should override any other language tag - if name == 'injection.language' then - local text = vim.treesitter.get_node_text(node, self._source, { metadata = metadata[id] }) - lang = resolve_lang(text) - elseif name == 'injection.content' then - ranges = get_node_ranges(node, self._source, metadata[id], include_children) + for id, nodes in pairs(match) do + for _, node in ipairs(nodes) do + local name = self._injection_query.captures[id] + -- Lang should override any other language tag + if name == 'injection.language' then + local text = vim.treesitter.get_node_text(node, self._source, { metadata = metadata[id] }) + lang = resolve_lang(text) + elseif name == 'injection.content' then + ranges = get_node_ranges(node, self._source, metadata[id], include_children) + end end end @@ -844,7 +846,13 @@ function LanguageTree:_get_injections() local start_line, _, end_line, _ = root_node:range() for pattern, match, metadata in - self._injection_query:iter_matches(root_node, self._source, start_line, end_line + 1) + self._injection_query:iter_matches( + root_node, + self._source, + start_line, + end_line + 1, + { all = true } + ) do local lang, combined, ranges = self:_get_injection(match, metadata) if lang then diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index cd65c0d7f6..5bb9e07a82 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -290,47 +290,71 @@ function M.get_node_text(...) return vim.treesitter.get_node_text(...) end ----@alias TSMatch table - ----@alias TSPredicate fun(match: TSMatch, _, _, predicate: any[]): boolean - --- Predicate handler receive the following arguments --- (match, pattern, bufnr, predicate) ----@type table -local predicate_handlers = { - ['eq?'] = function(match, _, source, predicate) - local node = match[predicate[2]] - if not node then +--- Implementations of predicates that can optionally be prefixed with "any-". +--- +--- These functions contain the implementations for each predicate, correctly +--- handling the "any" vs "all" semantics. They are called from the +--- predicate_handlers table with the appropriate arguments for each predicate. +local impl = { + --- @param match TSMatch + --- @param source integer|string + --- @param predicate any[] + --- @param any boolean + ['eq'] = function(match, source, predicate, any) + local nodes = match[predicate[2]] + if not nodes or #nodes == 0 then return true end - local node_text = vim.treesitter.get_node_text(node, source) - local str ---@type string - if type(predicate[3]) == 'string' then - -- (#eq? @aa "foo") - str = predicate[3] - else - -- (#eq? @aa @bb) - str = vim.treesitter.get_node_text(match[predicate[3]], source) - end + for _, node in ipairs(nodes) do + local node_text = vim.treesitter.get_node_text(node, source) + + local str ---@type string + if type(predicate[3]) == 'string' then + -- (#eq? @aa "foo") + str = predicate[3] + else + -- (#eq? @aa @bb) + local other = assert(match[predicate[3]]) + assert(#other == 1, '#eq? does not support comparison with captures on multiple nodes') + str = vim.treesitter.get_node_text(other[1], source) + end - if node_text ~= str or str == nil then - return false + local res = str ~= nil and node_text == str + if any and res then + return true + elseif not any and not res then + return false + end end - return true + return not any end, - ['lua-match?'] = function(match, _, source, predicate) - local node = match[predicate[2]] - if not node then + --- @param match TSMatch + --- @param source integer|string + --- @param predicate any[] + --- @param any boolean + ['lua-match'] = function(match, source, predicate, any) + local nodes = match[predicate[2]] + if not nodes or #nodes == 0 then return true end - local regex = predicate[3] - return string.find(vim.treesitter.get_node_text(node, source), regex) ~= nil + + for _, node in ipairs(nodes) do + local regex = predicate[3] + local res = string.find(vim.treesitter.get_node_text(node, source), regex) ~= nil + if any and res then + return true + elseif not any and not res then + return false + end + end + + return not any end, - ['match?'] = (function() + ['match'] = (function() local magic_prefixes = { ['\\v'] = true, ['\\m'] = true, ['\\M'] = true, ['\\V'] = true } local function check_magic(str) if string.len(str) < 2 or magic_prefixes[string.sub(str, 1, 2)] then @@ -347,85 +371,160 @@ local predicate_handlers = { end, }) - return function(match, _, source, pred) - ---@cast match TSMatch - local node = match[pred[2]] - if not node then + --- @param match TSMatch + --- @param source integer|string + --- @param predicate any[] + --- @param any boolean + return function(match, source, predicate, any) + local nodes = match[predicate[2]] + if not nodes or #nodes == 0 then return true end - ---@diagnostic disable-next-line no-unknown - local regex = compiled_vim_regexes[pred[3]] - return regex:match_str(vim.treesitter.get_node_text(node, source)) + + for _, node in ipairs(nodes) do + local regex = compiled_vim_regexes[predicate[3]] ---@type vim.regex + local res = regex:match_str(vim.treesitter.get_node_text(node, source)) + if any and res then + return true + elseif not any and not res then + return false + end + end + return not any end end)(), - ['contains?'] = function(match, _, source, predicate) - local node = match[predicate[2]] - if not node then + --- @param match TSMatch + --- @param source integer|string + --- @param predicate any[] + --- @param any boolean + ['contains'] = function(match, source, predicate, any) + local nodes = match[predicate[2]] + if not nodes or #nodes == 0 then return true end - local node_text = vim.treesitter.get_node_text(node, source) - for i = 3, #predicate do - if string.find(node_text, predicate[i], 1, true) then - return true + for _, node in ipairs(nodes) do + local node_text = vim.treesitter.get_node_text(node, source) + + for i = 3, #predicate do + local res = string.find(node_text, predicate[i], 1, true) + if any and res then + return true + elseif not any and not res then + return false + end end end - return false + return not any + end, +} + +---@class TSMatch +---@field pattern? integer +---@field active? boolean +---@field [integer] TSNode[] + +---@alias TSPredicate fun(match: TSMatch, pattern: integer, source: integer|string, predicate: any[]): boolean + +-- Predicate handler receive the following arguments +-- (match, pattern, bufnr, predicate) +---@type table +local predicate_handlers = { + ['eq?'] = function(match, _, source, predicate) + return impl['eq'](match, source, predicate, false) + end, + + ['any-eq?'] = function(match, _, source, predicate) + return impl['eq'](match, source, predicate, true) + end, + + ['lua-match?'] = function(match, _, source, predicate) + return impl['lua-match'](match, source, predicate, false) + end, + + ['any-lua-match?'] = function(match, _, source, predicate) + return impl['lua-match'](match, source, predicate, true) + end, + + ['match?'] = function(match, _, source, predicate) + return impl['match'](match, source, predicate, false) + end, + + ['any-match?'] = function(match, _, source, predicate) + return impl['match'](match, source, predicate, true) + end, + + ['contains?'] = function(match, _, source, predicate) + return impl['contains'](match, source, predicate, false) + end, + + ['any-contains?'] = function(match, _, source, predicate) + return impl['contains'](match, source, predicate, true) end, ['any-of?'] = function(match, _, source, predicate) - local node = match[predicate[2]] - if not node then + local nodes = match[predicate[2]] + if not nodes or #nodes == 0 then return true end - local node_text = vim.treesitter.get_node_text(node, source) - -- Since 'predicate' will not be used by callers of this function, use it - -- to store a string set built from the list of words to check against. - local string_set = predicate['string_set'] - if not string_set then - string_set = {} - for i = 3, #predicate do - ---@diagnostic disable-next-line:no-unknown - string_set[predicate[i]] = true + for _, node in ipairs(nodes) do + local node_text = vim.treesitter.get_node_text(node, source) + + -- Since 'predicate' will not be used by callers of this function, use it + -- to store a string set built from the list of words to check against. + local string_set = predicate['string_set'] --- @type table + if not string_set then + string_set = {} + for i = 3, #predicate do + string_set[predicate[i]] = true + end + predicate['string_set'] = string_set + end + + if string_set[node_text] then + return true end - predicate['string_set'] = string_set end - return string_set[node_text] + return false end, ['has-ancestor?'] = function(match, _, _, predicate) - local node = match[predicate[2]] - if not node then + local nodes = match[predicate[2]] + if not nodes or #nodes == 0 then return true end - local ancestor_types = {} - for _, type in ipairs({ unpack(predicate, 3) }) do - ancestor_types[type] = true - end + for _, node in ipairs(nodes) do + local ancestor_types = {} --- @type table + for _, type in ipairs({ unpack(predicate, 3) }) do + ancestor_types[type] = true + end - node = node:parent() - while node do - if ancestor_types[node:type()] then - return true + local cur = node:parent() + while cur do + if ancestor_types[cur:type()] then + return true + end + cur = cur:parent() end - node = node:parent() end return false end, ['has-parent?'] = function(match, _, _, predicate) - local node = match[predicate[2]] - if not node then + local nodes = match[predicate[2]] + if not nodes or #nodes == 0 then return true end - if vim.list_contains({ unpack(predicate, 3) }, node:parent():type()) then - return true + for _, node in ipairs(nodes) do + if vim.list_contains({ unpack(predicate, 3) }, node:parent():type()) then + return true + end end return false end, @@ -433,6 +532,7 @@ local predicate_handlers = { -- As we provide lua-match? also expose vim-match? predicate_handlers['vim-match?'] = predicate_handlers['match?'] +predicate_handlers['any-vim-match?'] = predicate_handlers['any-match?'] ---@class TSMetadata ---@field range? Range @@ -468,13 +568,17 @@ local directive_handlers = { -- Shifts the range of a node. -- Example: (#offset! @_node 0 1 0 -1) ['offset!'] = function(match, _, _, pred, metadata) - ---@cast pred integer[] - local capture_id = pred[2] + local capture_id = pred[2] --[[@as integer]] + local nodes = match[capture_id] + assert(#nodes == 1, '#offset! does not support captures on multiple nodes') + + local node = nodes[1] + if not metadata[capture_id] then metadata[capture_id] = {} end - local range = metadata[capture_id].range or { match[capture_id]:range() } + local range = metadata[capture_id].range or { node:range() } local start_row_offset = pred[3] or 0 local start_col_offset = pred[4] or 0 local end_row_offset = pred[5] or 0 @@ -498,7 +602,9 @@ local directive_handlers = { local id = pred[2] assert(type(id) == 'number') - local node = match[id] + local nodes = match[id] + assert(#nodes == 1, '#gsub! does not support captures on multiple nodes') + local node = nodes[1] local text = vim.treesitter.get_node_text(node, bufnr, { metadata = metadata[id] }) or '' if not metadata[id] then @@ -518,10 +624,9 @@ local directive_handlers = { local capture_id = pred[2] assert(type(capture_id) == 'number') - local node = match[capture_id] - if not node then - return - end + local nodes = match[capture_id] + assert(#nodes == 1, '#trim! does not support captures on multiple nodes') + local node = nodes[1] local start_row, start_col, end_row, end_col = node:range() @@ -552,38 +657,93 @@ local directive_handlers = { --- Adds a new predicate to be used in queries --- ---@param name string Name of the predicate, without leading # ----@param handler function(match:table, pattern:string, bufnr:integer, predicate:string[]) +---@param handler function(match: table, pattern: integer, source: integer|string, predicate: any[], metadata: table) --- - see |vim.treesitter.query.add_directive()| for argument meanings ----@param force boolean|nil -function M.add_predicate(name, handler, force) - if predicate_handlers[name] and not force then - error(string.format('Overriding %s', name)) +---@param opts table Optional options: +--- - force (boolean): Override an existing +--- predicate of the same name +--- - all (boolean): Use the correct +--- implementation of the match table where +--- capture IDs map to a list of nodes instead +--- of a single node. Defaults to false (for +--- backward compatibility). This option will +--- eventually become the default and removed. +function M.add_predicate(name, handler, opts) + -- Backward compatibility: old signature had "force" as boolean argument + if type(opts) == 'boolean' then + opts = { force = opts } end - predicate_handlers[name] = handler + opts = opts or {} + + if predicate_handlers[name] and not opts.force then + error(string.format('Overriding existing predicate %s', name)) + end + + if opts.all then + predicate_handlers[name] = handler + else + --- @param match table + local function wrapper(match, ...) + local m = {} ---@type table + for k, v in pairs(match) do + if type(k) == 'number' then + m[k] = v[#v] + end + end + return handler(m, ...) + end + predicate_handlers[name] = wrapper + end end --- Adds a new directive to be used in queries --- --- Handlers can set match level data by setting directly on the ---- metadata object `metadata.key = value`, additionally, handlers +--- metadata object `metadata.key = value`. Additionally, handlers --- can set node level data by using the capture id on the --- metadata table `metadata[capture_id].key = value` --- ---@param name string Name of the directive, without leading # ----@param handler function(match:table, pattern:string, bufnr:integer, predicate:string[], metadata:table) ---- - match: see |treesitter-query| ---- - node-level data are accessible via `match[capture_id]` ---- - pattern: see |treesitter-query| +---@param handler function(match: table, pattern: integer, source: integer|string, predicate: any[], metadata: table) +--- - match: A table mapping capture IDs to a list of captured nodes +--- - pattern: the index of the matching pattern in the query file --- - predicate: list of strings containing the full directive being called, e.g. --- `(node (#set! conceal "-"))` would get the predicate `{ "#set!", "conceal", "-" }` ----@param force boolean|nil -function M.add_directive(name, handler, force) - if directive_handlers[name] and not force then - error(string.format('Overriding %s', name)) +---@param opts table Optional options: +--- - force (boolean): Override an existing +--- predicate of the same name +--- - all (boolean): Use the correct +--- implementation of the match table where +--- capture IDs map to a list of nodes instead +--- of a single node. Defaults to false (for +--- backward compatibility). This option will +--- eventually become the default and removed. +function M.add_directive(name, handler, opts) + -- Backward compatibility: old signature had "force" as boolean argument + if type(opts) == 'boolean' then + opts = { force = opts } + end + + opts = opts or {} + + if directive_handlers[name] and not opts.force then + error(string.format('Overriding existing directive %s', name)) end - directive_handlers[name] = handler + if opts.all then + directive_handlers[name] = handler + else + --- @param match table + local function wrapper(match, ...) + local m = {} ---@type table + for k, v in pairs(match) do + m[k] = v[#v] + end + handler(m, ...) + end + directive_handlers[name] = wrapper + end end --- Lists the currently available directives to use in queries. @@ -608,7 +768,7 @@ end ---@private ---@param match TSMatch ----@param pattern string +---@param pattern integer ---@param source integer|string function Query:match_preds(match, pattern, source) local preds = self.info.patterns[pattern] @@ -618,18 +778,14 @@ function Query:match_preds(match, pattern, source) -- continue on the other case. This way unknown predicates will not be considered, -- which allows some testing and easier user extensibility (#12173). -- Also, tree-sitter strips the leading # from predicates for us. - local pred_name ---@type string - - local is_not ---@type boolean + local is_not = false -- Skip over directives... they will get processed after all the predicates. if not is_directive(pred[1]) then - if string.sub(pred[1], 1, 4) == 'not-' then - pred_name = string.sub(pred[1], 5) + local pred_name = pred[1] + if pred_name:match('^not%-') then + pred_name = pred_name:sub(5) is_not = true - else - pred_name = pred[1] - is_not = false end local handler = predicate_handlers[pred_name] @@ -724,7 +880,7 @@ function Query:iter_captures(node, source, start, stop) start, stop = value_or_node_range(start, stop, node) - local raw_iter = node:_rawquery(self.query, true, start, stop) + local raw_iter = node:_rawquery(self.query, true, start, stop) ---@type fun(): integer, TSNode, TSMatch local function iter(end_line) local capture, captured_node, match = raw_iter() local metadata = {} @@ -748,27 +904,34 @@ end --- Iterates the matches of self on a given range. --- ---- Iterate over all matches within a {node}. The arguments are the same as ---- for |Query:iter_captures()| but the iterated values are different: ---- an (1-based) index of the pattern in the query, a table mapping ---- capture indices to nodes, and metadata from any directives processing the match. ---- If the query has more than one pattern, the capture table might be sparse ---- and e.g. `pairs()` method should be used over `ipairs`. ---- Here is an example iterating over all captures in every match: +--- Iterate over all matches within a {node}. The arguments are the same as for +--- |Query:iter_captures()| but the iterated values are different: an (1-based) +--- index of the pattern in the query, a table mapping capture indices to a list +--- of nodes, and metadata from any directives processing the match. +--- +--- WARNING: Set `all=true` to ensure all matching nodes in a match are +--- returned, otherwise only the last node in a match is returned, breaking captures +--- involving quantifiers such as `(comment)+ @comment`. The default option +--- `all=false` is only provided for backward compatibility and will be removed +--- after Nvim 0.10. +--- +--- Example: --- --- ```lua ---- for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, first, last) do ---- for id, node in pairs(match) do +--- for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, 0, -1, { all = true }) do +--- for id, nodes in pairs(match) do --- local name = query.captures[id] ---- -- `node` was captured by the `name` capture in the match +--- for _, node in ipairs(nodes) do +--- -- `node` was captured by the `name` capture in the match --- ---- local node_data = metadata[id] -- Node level metadata ---- ---- -- ... use the info here ... +--- local node_data = metadata[id] -- Node level metadata +--- ... use the info here ... +--- end --- end --- end --- ``` --- +--- ---@param node TSNode under which the search will occur ---@param source (integer|string) Source buffer or string to search ---@param start? integer Starting line for the search. Defaults to `node:start()`. @@ -776,17 +939,20 @@ end ---@param opts? table Optional keyword arguments: --- - max_start_depth (integer) if non-zero, sets the maximum start depth --- for each match. This is used to prevent traversing too deep into a tree. +--- - all (boolean) When set, the returned match table maps capture IDs to a list of nodes. +--- Older versions of iter_matches incorrectly mapped capture IDs to a single node, which is +--- incorrect behavior. This option will eventually become the default and removed. --- ----@return (fun(): integer, table, table): pattern id, match, metadata +---@return (fun(): integer, table, table): pattern id, match, metadata function Query:iter_matches(node, source, start, stop, opts) + local all = opts and opts.all if type(source) == 'number' and source == 0 then source = api.nvim_get_current_buf() end start, stop = value_or_node_range(start, stop, node) - local raw_iter = node:_rawquery(self.query, false, start, stop, opts) - ---@cast raw_iter fun(): string, any + local raw_iter = node:_rawquery(self.query, false, start, stop, opts) ---@type fun(): integer, TSMatch local function iter() local pattern, match = raw_iter() local metadata = {} @@ -799,6 +965,18 @@ function Query:iter_matches(node, source, start, stop, opts) self:apply_directives(match, pattern, source, metadata) end + + if not all then + -- Convert the match table into the old buggy version for backward + -- compatibility. This is slow. Plugin authors, if you're reading this, set the "all" + -- option! + local old_match = {} ---@type table + for k, v in pairs(match or {}) do + old_match[k] = v[#v] + end + return pattern, old_match, metadata + end + return pattern, match, metadata end return iter -- cgit From 478273a4233d10b2ab898f1d38f4cfd491acc454 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Fri, 16 Feb 2024 14:00:19 -0600 Subject: fix: fix iter_matches call in query linter (#27496) --- runtime/lua/vim/treesitter/_query_linter.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua index 378e9c67aa..556c910feb 100644 --- a/runtime/lua/vim/treesitter/_query_linter.lua +++ b/runtime/lua/vim/treesitter/_query_linter.lua @@ -122,7 +122,7 @@ local parse = vim.func._memoize(hash_parse, function(node, buf, lang) end) --- @param buf integer ---- @param match table +--- @param match TSMatch --- @param query Query --- @param lang_context QueryLinterLanguageContext --- @param diagnostics Diagnostic[] @@ -175,7 +175,7 @@ function M.lint(buf, opts) parser:parse() parser:for_each_tree(function(tree, ltree) if ltree:lang() == 'query' then - for _, match, _ in query:iter_matches(tree:root(), buf, 0, -1) do + for _, match, _ in query:iter_matches(tree:root(), buf, 0, -1, { all = true }) do local lang_context = { lang = lang, parser_info = parser_info, -- cgit From a9f578b7a5edbca9aa01548f37341c2b97b57cda Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 19 Feb 2024 11:22:00 +0800 Subject: docs: improve 'tabline' click label docs (#27529) --- runtime/lua/vim/_meta/options.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 835bd95a3a..5a9215fa9e 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -6525,16 +6525,17 @@ vim.wo.stc = vim.wo.statuscolumn --- ) - End of item group. No width fields allowed. --- T N For 'tabline': start of tab page N label. Use %T or %X to end --- the label. Clicking this label with left mouse button switches ---- to the specified tab page. +--- to the specified tab page, while clicking it with middle mouse +--- button closes the specified tab page. --- X N For 'tabline': start of close tab N label. Use %X or %T to end --- the label, e.g.: %3Xclose%X. Use %999X for a "close current ---- tab" label. Clicking this label with left mouse button closes ---- specified tab page. ---- @ N Start of execute function label. Use %X or %T to ---- end the label, e.g.: %10@SwitchBuffer@foo.c%X. Clicking this ---- label runs specified function: in the example when clicking once ---- using left mouse button on "foo.c" "SwitchBuffer(10, 1, 'l', ---- ' ')" expression will be run. Function receives the +--- tab" label. Clicking this label with left mouse button closes +--- the specified tab page. +--- @ N Start of execute function label. Use %X or %T to end the label, +--- e.g.: %10@SwitchBuffer@foo.c%X. Clicking this label runs the +--- specified function: in the example when clicking once using left +--- mouse button on "foo.c", a `SwitchBuffer(10, 1, 'l', ' ')` +--- expression will be run. The specified function receives the --- following arguments in order: --- 1. minwid field value or zero if no N was specified --- 2. number of mouse clicks to detect multiple clicks -- cgit From cc15ba212c7992c3f3aae8b90962862572b21e83 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Sun, 18 Feb 2024 14:52:16 -0800 Subject: refactor(lsp): typings for protocol constants --- runtime/lua/vim/lsp/protocol.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 35eb0305d7..82e8c4a7de 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -1,6 +1,6 @@ --- Protocol for the Microsoft Language Server Protocol (mslsp) +--- @diagnostic disable: duplicate-doc-alias -local protocol = {} +-- Protocol for the Microsoft Language Server Protocol (mslsp) --[=[ ---@private @@ -20,7 +20,7 @@ function transform_schema_to_table() end --]=] -local constants = { +local protocol = { --- @enum lsp.DiagnosticSeverity DiagnosticSeverity = { -- Reports an error. @@ -313,7 +313,7 @@ local constants = { }, } -for k, v in pairs(constants) do +for k, v in pairs(protocol) do local tbl = vim.deepcopy(v, true) vim.tbl_add_reverse_lookup(tbl) protocol[k] = tbl @@ -723,7 +723,7 @@ function protocol.make_client_capabilities() codeActionLiteralSupport = { codeActionKind = { valueSet = (function() - local res = vim.tbl_values(constants.CodeActionKind) + local res = vim.tbl_values(protocol.CodeActionKind) table.sort(res) return res end)(), -- cgit From a0790558c3097f2813c56e404af30c3e2d8b8983 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 20 Feb 2024 19:53:49 +0800 Subject: fix(extmarks): priority order of inline and non-inline virt_text (#27532) --- runtime/lua/vim/_meta/api.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 0978f0acf5..31ef3dd64b 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -576,9 +576,10 @@ function vim.api.nvim_buf_line_count(buffer) end --- hidden marks, an "invalid" key is added to the "details" --- array of `nvim_buf_get_extmarks()` and family. If --- "undo_restore" is false, the extmark is deleted instead. ---- • priority: a priority value for the highlight group or sign ---- attribute. For example treesitter highlighting uses a ---- value of 100. +--- • priority: a priority value for the highlight group, sign +--- attribute or virtual text. For virtual text, item with +--- highest priority is drawn last. For example treesitter +--- highlighting uses a value of 100. --- • strict: boolean that indicates extmark should not be --- placed if the line or column value is past the end of the --- buffer or end of the line respectively. Defaults to true. -- cgit From 5e4a5f1aaa15be3bc17c5e96040fd71196993937 Mon Sep 17 00:00:00 2001 From: Vu Nhat Chuong Date: Wed, 21 Feb 2024 00:14:50 +0700 Subject: fix(vim.ui.open): use explorer.exe instead of wslview #26947 Problem: `vim.ui.open` uses `wslview`, which is slow and require a package from external PPA: https://wslutiliti.es/wslu/install.html#ubuntu Solution: Use `explorer.exe` instead. WSL supports it by default: https://learn.microsoft.com/en-us/windows/wsl/filesystems#view-your-current-directory-in-windows-file-explorer --- runtime/lua/vim/ui.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua index 25ced18daf..157b1461c3 100644 --- a/runtime/lua/vim/ui.lua +++ b/runtime/lua/vim/ui.lua @@ -143,12 +143,12 @@ function M.open(path) else return nil, 'vim.ui.open: rundll32 not found' end - elseif vim.fn.executable('wslview') == 1 then - cmd = { 'wslview', path } + elseif vim.fn.executable('explorer.exe') == 1 then + cmd = { 'explorer.exe', path } elseif vim.fn.executable('xdg-open') == 1 then cmd = { 'xdg-open', path } else - return nil, 'vim.ui.open: no handler found (tried: wslview, xdg-open)' + return nil, 'vim.ui.open: no handler found (tried: explorer.exe, xdg-open)' end local rv = vim.system(cmd, { text = true, detach = true }):wait() -- cgit From f25c0c1eb9be7664ed01a648008e55b406c6222a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 21 Feb 2024 06:29:53 +0800 Subject: vim-patch:ef387c062bb1 (#27553) runtime(filetype): Modula-2 files with priority not detected (vim/vim#14055) Problem: Modula-2 files with a specified priority are not detected. Solution: Match the priority syntax in module header lines when performing heuristic content detection. Disable the :defcompile debug line. This was accidentally left enabled in commit 68a8947. https://github.com/vim/vim/commit/ef387c062bb1966187d3f307d697d80162051a0d Co-authored-by: dkearns --- runtime/lua/vim/filetype/detect.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua index ce3b873e40..3db4f2bcdc 100644 --- a/runtime/lua/vim/filetype/detect.lua +++ b/runtime/lua/vim/filetype/detect.lua @@ -422,7 +422,7 @@ end --- @param bufnr integer --- @return boolean local function is_modula2(bufnr) - return matchregex(nextnonblank(bufnr, 1), [[\ Date: Wed, 21 Feb 2024 03:31:56 -0800 Subject: fix(lsp): add parentheses to generated union array types (#27560) --- runtime/lua/vim/lsp/_meta/protocol.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/_meta/protocol.lua b/runtime/lua/vim/lsp/_meta/protocol.lua index b897b6bba5..a5da5ac6b7 100644 --- a/runtime/lua/vim/lsp/_meta/protocol.lua +++ b/runtime/lua/vim/lsp/_meta/protocol.lua @@ -409,7 +409,7 @@ error('Cannot require a meta file') --- ---If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then ---only plain `TextEdit`s using the `changes` property are supported. ----@field documentChanges? lsp.TextDocumentEdit|lsp.CreateFile|lsp.RenameFile|lsp.DeleteFile[] +---@field documentChanges? (lsp.TextDocumentEdit|lsp.CreateFile|lsp.RenameFile|lsp.DeleteFile)[] --- ---A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and ---delete file / folder operations. @@ -1888,7 +1888,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 - support for AnnotatedTextEdit. This is guarded using a ---client capability. ----@field edits lsp.TextEdit|lsp.AnnotatedTextEdit[] +---@field edits (lsp.TextEdit|lsp.AnnotatedTextEdit)[] ---Create file operation. ---@class lsp.CreateFile: lsp.ResourceOperation @@ -3146,7 +3146,7 @@ error('Cannot require a meta file') ---@class lsp.NotebookDocumentSyncOptions --- ---The notebooks to be synced ----@field notebookSelector lsp._anonym14.notebookSelector|lsp._anonym16.notebookSelector[] +---@field notebookSelector (lsp._anonym14.notebookSelector|lsp._anonym16.notebookSelector)[] --- ---Whether save notification should be forwarded to ---the server. Will only be honored if mode === `notebook`. -- cgit From 6d8bbfe19df2175637a1e47ac1aafb0e96e35b38 Mon Sep 17 00:00:00 2001 From: rktjmp Date: Thu, 22 Feb 2024 00:25:08 +1100 Subject: docs: remove mention of foreground/background/special keys in nvim_set_hl (#27558) To align the output of `nvim_get_hl` with its documentation -- which points to `nvim_set_hl`, remove mentions of the keys `foreground`, `background` and `special`. The long keys are are still supported (via fallback checks inside `dict2hlattrs`), but the `fg`, `bg` and `sp` keys are preferenced. --- runtime/lua/vim/_meta/api.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 31ef3dd64b..cfdb65c2b5 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1819,9 +1819,9 @@ function vim.api.nvim_set_decoration_provider(ns_id, opts) end --- activate them. --- @param name string Highlight group name, e.g. "ErrorMsg" --- @param val vim.api.keyset.highlight Highlight definition map, accepts the following keys: ---- • fg (or foreground): color name or "#RRGGBB", see note. ---- • bg (or background): color name or "#RRGGBB", see note. ---- • sp (or special): color name or "#RRGGBB" +--- • fg: color name or "#RRGGBB", see note. +--- • bg: color name or "#RRGGBB", see note. +--- • sp: color name or "#RRGGBB" --- • blend: integer between 0 and 100 --- • bold: boolean --- • standout: boolean -- cgit From 1c032ad703a19cd5c8498ee95f9352df87a91139 Mon Sep 17 00:00:00 2001 From: altermo <107814000+altermo@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:52:42 +0100 Subject: feat(extmark): window scoped extmark Co-authored-by: zeertzjq --- runtime/lua/vim/_meta/api.lua | 22 ++++++++++++++++++++++ runtime/lua/vim/_meta/api_keysets.lua | 1 + 2 files changed, 23 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index cfdb65c2b5..998608ae16 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -613,6 +613,8 @@ function vim.api.nvim_buf_line_count(buffer) end --- • url: A URL to associate with this extmark. In the TUI, the --- OSC 8 control sequence is used to generate a clickable --- hyperlink to this URL. +--- • scoped: boolean that indicates that the extmark should +--- only be displayed in the namespace scope. (experimental) --- @return integer function vim.api.nvim_buf_set_extmark(buffer, ns_id, line, col, opts) end @@ -1982,6 +1984,13 @@ function vim.api.nvim_tabpage_set_var(tabpage, name, value) end --- @param win integer Window handle, must already belong to {tabpage} function vim.api.nvim_tabpage_set_win(tabpage, win) end +--- Adds the namespace scope to the window. +--- +--- @param window integer Window handle, or 0 for current window +--- @param ns_id integer the namespace to add +--- @return boolean +function vim.api.nvim_win_add_ns(window, ns_id) end + --- Calls a function with window as temporary current window. --- --- @param window integer Window handle, or 0 for current window @@ -2032,6 +2041,12 @@ function vim.api.nvim_win_get_cursor(window) end --- @return integer function vim.api.nvim_win_get_height(window) end +--- Gets all the namespaces scopes associated with a window. +--- +--- @param window integer Window handle, or 0 for current window +--- @return integer[] +function vim.api.nvim_win_get_ns(window) end + --- Gets the window number --- --- @param window integer Window handle, or 0 for current window @@ -2084,6 +2099,13 @@ function vim.api.nvim_win_hide(window) end --- @return boolean function vim.api.nvim_win_is_valid(window) end +--- Removes the namespace scope from the window. +--- +--- @param window integer Window handle, or 0 for current window +--- @param ns_id integer the namespace to remove +--- @return boolean +function vim.api.nvim_win_remove_ns(window, ns_id) end + --- Sets the current buffer in a window, without side effects --- --- @param window integer Window handle, or 0 for current window diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index ab0d3aafe8..37e4372196 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -252,6 +252,7 @@ error('Cannot require a meta file') --- @field ui_watched? boolean --- @field undo_restore? boolean --- @field url? string +--- @field scoped? boolean --- @field _subpriority? integer --- @class vim.api.keyset.user_command -- cgit From e2e63bd045491f36e12c924fddbe76b3ef884b38 Mon Sep 17 00:00:00 2001 From: altermo <107814000+altermo@users.noreply.github.com> Date: Thu, 22 Feb 2024 09:39:32 +0100 Subject: fix(lua): make highlight.on_yank use win-local highlight (#27349) Currently, highlight.on_yank() does buffer-local highlighting, this PR makes it window scoped. Also fix the problem that when yanking in a buffer, moving to another buffer, and yanking before the original buffer highlight disappears, the original buffer highlight won't disappear on timeout. --- runtime/lua/vim/highlight.lua | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua index 1d04f95d2d..b055cce49d 100644 --- a/runtime/lua/vim/highlight.lua +++ b/runtime/lua/vim/highlight.lua @@ -55,6 +55,7 @@ function M.range(bufnr, ns, higroup, start, finish, opts) local regtype = opts.regtype or 'v' local inclusive = opts.inclusive or false local priority = opts.priority or M.priorities.user + local scoped = opts._scoped or false -- TODO: in case of 'v', 'V' (not block), this should calculate equivalent -- bounds (row, col, end_row, end_col) as multiline regions are natively @@ -72,12 +73,14 @@ function M.range(bufnr, ns, higroup, start, finish, opts) end_col = cols[2], priority = priority, strict = false, + scoped = scoped, }) end end local yank_ns = api.nvim_create_namespace('hlyank') local yank_timer +local yank_cancel --- Highlight the yanked text --- @@ -120,24 +123,29 @@ function M.on_yank(opts) local higroup = opts.higroup or 'IncSearch' local timeout = opts.timeout or 150 - local bufnr = api.nvim_get_current_buf() - api.nvim_buf_clear_namespace(bufnr, yank_ns, 0, -1) + local bufnr = vim.api.nvim_get_current_buf() + local winid = vim.api.nvim_get_current_win() if yank_timer then yank_timer:close() + yank_cancel() end M.range(bufnr, yank_ns, higroup, "'[", "']", { regtype = event.regtype, inclusive = event.inclusive, priority = opts.priority or M.priorities.user, + _scoped = true, }) + vim.api.nvim_win_add_ns(winid, yank_ns) - yank_timer = vim.defer_fn(function() + yank_cancel = function() yank_timer = nil - if api.nvim_buf_is_valid(bufnr) then - api.nvim_buf_clear_namespace(bufnr, yank_ns, 0, -1) - end - end, timeout) + yank_cancel = nil + pcall(vim.api.nvim_buf_clear_namespace, bufnr, yank_ns, 0, -1) + pcall(vim.api.nvim_win_remove_ns, winid, yank_ns) + end + + yank_timer = vim.defer_fn(yank_cancel, timeout) end return M -- cgit From eef2aedff6313d85b852463c78614ace57bb6f56 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 22 Feb 2024 21:15:56 +0800 Subject: fix(defaults): remove tmux background detection passthrough (#27571) There is now a new tmux 3.4 release that queries background color from the parent terminal if background is not set in tmux, so removing the passthrough still works when background is not set in tmux, and fixes the incorrect detection when background is set in tmux. --- runtime/lua/vim/_defaults.lua | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 07850a5a47..f453264c76 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -343,17 +343,7 @@ if tty then end, }) - local query = '\027]11;?\007' - - -- tmux 3.3a and earlier do not query the parent terminal for background color. As of the - -- writing of this comment, 3.3a is the latest release, so a passthrough sequence is necessary. - -- The passthrough should be removed as soon as a tmux version later than 3.3a is released. - -- See: https://github.com/neovim/neovim/pull/26557 - if os.getenv('TMUX') then - query = string.format('\027Ptmux;%s\027\\', query:gsub('\027', '\027\027')) - end - - io.stdout:write(query) + io.stdout:write('\027]11;?\007') timer:start(1000, 0, function() -- Delete the autocommand if no response was received -- cgit From 85cb0b0ddc59cd1b3a911e5b4a358e5404c1d0d8 Mon Sep 17 00:00:00 2001 From: Evgeni Chasnovski Date: Thu, 22 Feb 2024 21:54:21 +0200 Subject: fix(defaults): make terminal autoclose not block other events (#27581) Problem: When terminal is autocloses, it blocks other events, like `BufEnter`. Solution: Use `nested = true`. --- runtime/lua/vim/_defaults.lua | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index f453264c76..6afb1d6b1c 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -143,14 +143,16 @@ do vim.api.nvim_create_autocmd({ 'TermClose' }, { group = nvim_terminal_augroup, + nested = true, desc = 'Automatically close terminal buffers when started with no arguments and exiting without an error', callback = function(args) - if vim.v.event.status == 0 then - local info = vim.api.nvim_get_chan_info(vim.bo[args.buf].channel) - local argv = info.argv or {} - if #argv == 1 and argv[1] == vim.o.shell then - vim.cmd({ cmd = 'bdelete', args = { args.buf }, bang = true }) - end + if vim.v.event.status ~= 0 then + return + end + local info = vim.api.nvim_get_chan_info(vim.bo[args.buf].channel) + local argv = info.argv or {} + if #argv == 1 and argv[1] == vim.o.shell then + vim.api.nvim_buf_delete(args.buf, { force = true }) end end, }) -- cgit From bb15fa035610bb9765ca16900703804a88faa3bb Mon Sep 17 00:00:00 2001 From: 再生花 Date: Fri, 23 Feb 2024 05:58:59 +0900 Subject: feat(treesitter): add folding for `InspectTree` (#27518) As the InspectTree buffer is now a valid tree-sitter query tree, we can use the bundled fold queries to have folding for the tree. --- runtime/lua/vim/treesitter.lua | 3 ++- runtime/lua/vim/treesitter/dev.lua | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 88b68ff658..2aa46ceebd 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -461,7 +461,8 @@ end --- --- While in the window, press "a" to toggle display of anonymous nodes, "I" to toggle the --- display of the source language of each node, "o" to toggle the query editor, and press ---- to jump to the node under the cursor in the source buffer. +--- to jump to the node under the cursor in the source buffer. Folding also works +--- (try |zo|, |zc|, etc.). --- --- Can also be shown with `:InspectTree`. *:InspectTree* --- diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 551067533a..4c8f6e466f 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -159,7 +159,10 @@ end local function set_dev_properties(w, b) vim.wo[w].scrolloff = 5 vim.wo[w].wrap = false - vim.wo[w].foldmethod = 'manual' -- disable folding + vim.wo[w].foldmethod = 'expr' + vim.wo[w].foldexpr = 'v:lua.vim.treesitter.foldexpr()' -- explicitly set foldexpr + vim.wo[w].foldenable = false -- Don't fold on first open InspectTree + vim.wo[w].foldlevel = 99 vim.bo[b].buflisted = false vim.bo[b].buftype = 'nofile' vim.bo[b].bufhidden = 'wipe' -- cgit From 20e4001eeedc80b1f2857fcaca81f7a211a09b40 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 22 Feb 2024 20:32:52 +0800 Subject: vim-patch:9.1.0120: hard to get visual region using Vim script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: hard to get visual region using Vim script Solution: Add getregion() Vim script function (Shougo Matsushita, Jakub Łuczyński) closes: vim/vim#13998 closes: vim/vim#11579 https://github.com/vim/vim/commit/3f905ab3c4f66562f4a224bf00f49d98a0b0da91 Cherry-pick changes from patch 9.1.0122, with :echom instead of :echow. Co-authored-by: Shougo Matsushita Co-authored-by: Jakub Łuczyński --- runtime/lua/vim/_meta/vimfn.lua | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 224cecf144..527113c016 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -3525,6 +3525,46 @@ function vim.fn.getreg(regname, list) end --- @return table function vim.fn.getreginfo(regname) end +--- Returns the list of strings from {pos1} to {pos2} as if it's +--- selected in visual mode of {type}. +--- For possible values of {pos1} and {pos2} see |line()|. +--- {type} is the selection type: +--- "v" for |charwise| mode +--- "V" for |linewise| mode +--- "" for |blockwise-visual| mode +--- You can get the last selection type by |visualmode()|. +--- If Visual mode is active, use |mode()| to get the Visual mode +--- (e.g., in a |:vmap|). +--- This function uses the line and column number from the +--- specified position. +--- It is useful to get text starting and ending in different +--- columns, such as |charwise-visual| selection. +--- +--- Note that: +--- - Order of {pos1} and {pos2} doesn't matter, it will always +--- return content from the upper left position to the lower +--- right position. +--- - If 'virtualedit' is enabled and selection is past the end of +--- line, resulting lines are filled with blanks. +--- - If the selection starts or ends in the middle of a multibyte +--- character, it is not included but its selected part is +--- substituted with spaces. +--- - If {pos1} or {pos2} equals "v" (see |line()|) and it is not in +--- |visual-mode|, an empty list is returned. +--- - If {pos1}, {pos2} or {type} is an invalid string, an empty +--- list is returned. +--- +--- Examples: > +--- :xnoremap +--- \ echom getregion('v', '.', mode()) +--- < +--- +--- @param pos1 string +--- @param pos2 string +--- @param type string +--- @return string[] +function vim.fn.getregion(pos1, pos2, type) end + --- The result is a String, which is type of register {regname}. --- The value will be one of: --- "v" for |charwise| text -- cgit From 06df895e71720b65f98b6b9c579ca5918a12bc04 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 23 Feb 2024 06:35:40 +0800 Subject: vim-patch:9.1.0126: Internal error when using upper-case mark in getregion() Problem: Internal error when passing mark in another buffer to getregion(). Solution: Don't allow marks in another buffer (zeertzjq) closes: vim/vim#14076 Internal error when passing mark in another buffer to getregion() https://github.com/vim/vim/commit/421b597470c118871c7081de00dd065e0e000b7e --- runtime/lua/vim/_meta/vimfn.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 527113c016..623ce2bc0f 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -3553,6 +3553,8 @@ function vim.fn.getreginfo(regname) end --- |visual-mode|, an empty list is returned. --- - If {pos1}, {pos2} or {type} is an invalid string, an empty --- list is returned. +--- - If {pos1} or {pos2} is a mark in different buffer, an empty +--- list is returned. --- --- Examples: > --- :xnoremap -- cgit From eb4783fb6c8c16d3a9a10e5ef36312737fc9bc40 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 23 Feb 2024 08:12:46 +0800 Subject: refactor(defaults): use getregion() for default * and # mappings --- runtime/lua/vim/_defaults.lua | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 6afb1d6b1c..32534a89b4 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -4,27 +4,9 @@ do --- --- See |v_star-default| and |v_#-default| do - local function region_chunks(region) - local chunks = {} - local maxcol = vim.v.maxcol - for line, cols in vim.spairs(region) do - local endcol = cols[2] == maxcol and -1 or cols[2] - local chunk = vim.api.nvim_buf_get_text(0, line, cols[1], line, endcol, {})[1] - table.insert(chunks, chunk) - end - return chunks - end - local function _visual_search(cmd) assert(cmd == '/' or cmd == '?') - local region = vim.region( - 0, - '.', - 'v', - vim.api.nvim_get_mode().mode:sub(1, 1), - vim.o.selection == 'inclusive' - ) - local chunks = region_chunks(region) + local chunks = vim.fn.getregion('.', 'v', vim.fn.mode()) local esc_chunks = vim .iter(chunks) :map(function(v) -- cgit From 15f7ac6a045aad3355e4c6006423fde81644886a Mon Sep 17 00:00:00 2001 From: Tim Pope Date: Sat, 24 Feb 2024 01:19:33 -0500 Subject: docs(lsp): remove obsolete didChangeConfiguration explanation (#27595) Rendered obsolete by c6d747e6a5227e17556c62e16ed054398eb1a89a. --- runtime/lua/vim/lsp.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 8608bdfa57..689d942d72 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -641,10 +641,7 @@ end --- 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. Most language servers expect to be sent client specified settings after ---- initialization. Nvim does not make this assumption. A ---- `workspace/didChangeConfiguration` notification should be sent ---- to the server during on_init. +--- any notifications are sent. --- --- - on_exit Callback (code, signal, client_id) invoked on client --- exit. -- cgit From 9418381ccca5bf749b2f10b8a31d6e0900898ffa Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 24 Feb 2024 17:55:32 +0800 Subject: vim-patch:a35235e824bb (#27598) runtime(doc) Update help text for matchbufline() and matchstrlist() closes: vim/vim#14080 https://github.com/vim/vim/commit/a35235e824bb77df0cebdb2bd290e13f1201b292 Co-authored-by: Yegappan Lakshmanan --- runtime/lua/vim/_meta/vimfn.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 623ce2bc0f..07e6d42e1c 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -5356,6 +5356,7 @@ function vim.fn.mapset(dict) end --- Note that when {count} is added the way {start} works changes, --- see above. --- +--- *match-pattern* --- See |pattern| for the patterns that are accepted. --- The 'ignorecase' option is used to set the ignore-caseness of --- the pattern. 'smartcase' is NOT used. The matching is always @@ -5514,6 +5515,9 @@ function vim.fn.matcharg(nr) end --- This function works only for loaded buffers. First call --- |bufload()| if needed. --- +--- See |match-pattern| for information about the effect of some +--- option settings on the pattern. +--- --- When {buf} is not a valid buffer, the buffer is not loaded or --- {lnum} or {end} is not valid then an error is given and an --- empty |List| is returned. @@ -5727,6 +5731,9 @@ function vim.fn.matchstr(expr, pat, start, count) end --- submatches a List of submatches. Present only if --- "submatches" is set to v:true in {dict}. --- +--- See |match-pattern| for information about the effect of some +--- option settings on the pattern. +--- --- Example: >vim --- :echo matchstrlist(['tik tok'], '\<\k\+\>') --- [{'idx': 0, 'byteidx': 0, 'text': 'tik'}, {'idx': 0, 'byteidx': 4, 'text': 'tok'}] -- cgit From 90f6d999b12a93bb8a2aa9a735d2d77fc97b94db Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Sat, 24 Feb 2024 21:14:12 +0900 Subject: refactor(lsp): remove redundant code (#27601) * use builtin function * buffer:// was removed in 236c20795eb9f11e21e0719b735ea741711acc08. --- runtime/lua/vim/lsp/util.lua | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 4abc58ee3c..418eb5e159 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -639,21 +639,12 @@ function M.text_document_completion_list_to_complete_items(result, prefix) return vim.lsp._completion._lsp_to_complete_items(result, prefix) end ---- Like vim.fn.bufwinid except it works across tabpages. -local function bufwinid(bufnr) - for _, win in ipairs(api.nvim_list_wins()) do - if api.nvim_win_get_buf(win) == bufnr then - return win - end - end -end - --- Get list of buffers for a directory local function get_dir_bufs(path) path = path:gsub('([^%w])', '%%%1') local buffers = {} for _, v in ipairs(vim.api.nvim_list_bufs()) do - local bufname = vim.api.nvim_buf_get_name(v):gsub('buffer://', '') + local bufname = vim.api.nvim_buf_get_name(v) if bufname:find(path) then table.insert(buffers, v) end @@ -682,7 +673,7 @@ function M.rename(old_fname, new_fname, opts) else local oldbuf = vim.fn.bufadd(old_fname) table.insert(oldbufs, oldbuf) - win = bufwinid(oldbuf) + win = vim.fn.win_findbuf(oldbuf)[1] end for _, b in ipairs(oldbufs) do @@ -1061,7 +1052,7 @@ function M.show_document(location, offset_encoding, opts) vim.fn.settagstack(vim.fn.win_getid(), { items = items }, 't') end - local win = opts.reuse_win and bufwinid(bufnr) + local win = opts.reuse_win and vim.fn.win_findbuf(bufnr)[1] or focus and api.nvim_get_current_win() or create_window_without_focus() -- cgit From a0394b648c2486ce7085d3e6e7541024e1a3fe9a Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 24 Feb 2024 14:49:36 +0100 Subject: docs(lsp): mark `ClientConfig.init_options` as optional Followup to neovim/neovim#27443 --- runtime/lua/vim/lsp/client.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index a460d95cc6..c1b41a7183 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -21,7 +21,7 @@ local validate = vim.validate --- @field handlers? table --- @field settings? table --- @field commands? table ---- @field init_options table +--- @field init_options? table --- @field name? string --- @field get_language_id? fun(bufnr: integer, filetype: string): string --- @field offset_encoding? string -- cgit From 8addd27504e698da62176824209ae2d3d24247c0 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Sun, 25 Feb 2024 00:47:34 +0900 Subject: fix(lsp): when renaming directory, check path prefix of buffer names (#27603) For example, when renaming /path/to/dir, buffers like fern://drawer/file:///path/to/dir, /path/to/dir123 should not be matched. --- runtime/lua/vim/lsp/util.lua | 53 ++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 14 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 418eb5e159..444354fdc3 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -639,13 +639,28 @@ function M.text_document_completion_list_to_complete_items(result, prefix) return vim.lsp._completion._lsp_to_complete_items(result, prefix) end ---- Get list of buffers for a directory -local function get_dir_bufs(path) - path = path:gsub('([^%w])', '%%%1') +local function path_components(path) + return vim.split(path, '/', { plain = true }) +end + +local function path_under_prefix(path, prefix) + for i, c in ipairs(prefix) do + if c ~= path[i] then + return false + end + end + return true +end + +--- Get list of buffers whose filename matches the given path prefix (normalized full path) +---@return integer[] +local function get_bufs_with_prefix(prefix) + prefix = path_components(prefix) local buffers = {} for _, v in ipairs(vim.api.nvim_list_bufs()) do - local bufname = vim.api.nvim_buf_get_name(v) - if bufname:find(path) then + local bname = vim.api.nvim_buf_get_name(v) + local path = path_components(vim.fs.normalize(bname, { expand_env = false })) + if path_under_prefix(path, prefix) then table.insert(buffers, v) end end @@ -654,24 +669,34 @@ end --- Rename old_fname to new_fname --- ----@param opts (table) --- overwrite? bool --- ignoreIfExists? bool +---@param old_fname string +---@param new_fname string +---@param opts? table options +--- - overwrite? boolean +--- - ignoreIfExists? boolean function M.rename(old_fname, new_fname, opts) opts = opts or {} + local skip = not opts.overwrite or opts.ignoreIfExists + + local old_fname_full = vim.uv.fs_realpath(vim.fs.normalize(old_fname, { expand_env = false })) + if not old_fname_full then + vim.notify('Invalid path: ' .. old_fname, vim.log.levels.ERROR) + return + end + local target_exists = uv.fs_stat(new_fname) ~= nil - if target_exists and not opts.overwrite or opts.ignoreIfExists then - vim.notify('Rename target already exists. Skipping rename.') + if target_exists and skip then + vim.notify(new_fname .. ' already exists. Skipping rename.', vim.log.levels.ERROR) return end local oldbufs = {} local win = nil - if vim.fn.isdirectory(old_fname) == 1 then - oldbufs = get_dir_bufs(old_fname) + if vim.fn.isdirectory(old_fname_full) == 1 then + oldbufs = get_bufs_with_prefix(old_fname_full) else - local oldbuf = vim.fn.bufadd(old_fname) + local oldbuf = vim.fn.bufadd(old_fname_full) table.insert(oldbufs, oldbuf) win = vim.fn.win_findbuf(oldbuf)[1] end @@ -687,7 +712,7 @@ function M.rename(old_fname, new_fname, opts) local newdir = assert(vim.fs.dirname(new_fname)) vim.fn.mkdir(newdir, 'p') - local ok, err = os.rename(old_fname, new_fname) + local ok, err = os.rename(old_fname_full, new_fname) assert(ok, err) if vim.fn.isdirectory(new_fname) == 0 then -- cgit From c2ddef30e743d8c1de6d960bf230b8646cb49c7c Mon Sep 17 00:00:00 2001 From: Evgeni Chasnovski Date: Sun, 25 Feb 2024 02:45:34 +0200 Subject: docs: fix several misleading and superfluous wordings (#27609) --- runtime/lua/vim/_meta/api.lua | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 998608ae16..aee866f324 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -584,21 +584,16 @@ function vim.api.nvim_buf_line_count(buffer) end --- placed if the line or column value is past the end of the --- buffer or end of the line respectively. Defaults to true. --- • sign_text: string of length 1-2 used to display in the ---- sign column. Note: ranges are unsupported and decorations ---- are only applied to start_row +--- sign column. --- • sign_hl_group: name of the highlight group used to ---- highlight the sign column text. Note: ranges are ---- unsupported and decorations are only applied to start_row +--- highlight the sign column text. --- • number_hl_group: name of the highlight group used to ---- highlight the number column. Note: ranges are unsupported ---- and decorations are only applied to start_row +--- highlight the number column. --- • line_hl_group: name of the highlight group used to ---- highlight the whole line. Note: ranges are unsupported and ---- decorations are only applied to start_row +--- highlight the whole line. --- • cursorline_hl_group: name of the highlight group used to ---- highlight the line when the cursor is on the same line as ---- the mark and 'cursorline' is enabled. Note: ranges are ---- unsupported and decorations are only applied to start_row +--- highlight the sign column text when the cursor is on the +--- same line as the mark and 'cursorline' is enabled. --- • conceal: string which should be either empty or a single --- character. Enable concealing similar to `:syn-conceal`. --- When a character is supplied it is used as `:syn-cchar`. @@ -1807,7 +1802,7 @@ function vim.api.nvim_set_current_win(window) end --- • on_win: called when starting to redraw a specific window. --- ["win", winid, bufnr, topline, botline] --- • on_line: called for each buffer line being redrawn. (The ---- interaction with fold lines is subject to change) ["win", +--- interaction with fold lines is subject to change) ["line", --- winid, bufnr, row] --- • on_end: called at the end of a redraw cycle ["end", tick] function vim.api.nvim_set_decoration_provider(ns_id, opts) end -- cgit From 2e1f5055acdef650c27efc4afdf8606037ec021b Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Sat, 24 Feb 2024 19:21:57 -0600 Subject: fix(lsp): add assertion for explicit bufnr in apply_text_edits (#27614) Assert that the buffer number passed to apply_text_edits is fully resolved (not 0 or null). Pass the known buffer number to apply_text_edits from lsp.formatexpr(). --- runtime/lua/vim/lsp.lua | 2 +- runtime/lua/vim/lsp/util.lua | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 689d942d72..3a74c3ee90 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1280,7 +1280,7 @@ function lsp.formatexpr(opts) local response = client.request_sync(ms.textDocument_rangeFormatting, params, timeout_ms, bufnr) if response and response.result then - lsp.util.apply_text_edits(response.result, 0, client.offset_encoding) + lsp.util.apply_text_edits(response.result, bufnr, client.offset_encoding) return 0 end end diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 444354fdc3..b60135f851 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -419,6 +419,9 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) if not next(text_edits) then return end + + assert(bufnr ~= 0, 'Explicit buffer number is required') + if not api.nvim_buf_is_loaded(bufnr) then vim.fn.bufload(bufnr) end @@ -457,7 +460,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) -- save and restore local marks since they get deleted by nvim_buf_set_lines local marks = {} - for _, m in pairs(vim.fn.getmarklist(bufnr or vim.api.nvim_get_current_buf())) do + for _, m in pairs(vim.fn.getmarklist(bufnr)) do if m.mark:match("^'[a-z]$") then marks[m.mark:sub(2, 2)] = { m.pos[2], m.pos[3] - 1 } -- api-indexed end @@ -516,7 +519,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) local max = api.nvim_buf_line_count(bufnr) -- no need to restore marks that still exist - for _, m in pairs(vim.fn.getmarklist(bufnr or vim.api.nvim_get_current_buf())) do + for _, m in pairs(vim.fn.getmarklist(bufnr)) do marks[m.mark:sub(2, 2)] = nil end -- restore marks -- cgit From 185752614d1a4906c8f218e4c24c3b52bbe6560e Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Sun, 18 Feb 2024 18:46:19 -0800 Subject: refactor(types): fix miscellaneous type warnings --- runtime/lua/vim/treesitter.lua | 11 +++++++++-- runtime/lua/vim/treesitter/highlighter.lua | 2 +- runtime/lua/vim/ui.lua | 9 +++++---- runtime/lua/vim/version.lua | 19 ++++++++++++------- 4 files changed, 27 insertions(+), 14 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 2aa46ceebd..e2197168f0 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -294,6 +294,7 @@ function M.get_captures_at_pos(bufnr, row, col) for capture, node, metadata in iter do if M.is_in_node_range(node, row, col) then + ---@diagnostic disable-next-line: invisible local c = q._query.captures[capture] -- name of the capture in the query if c ~= nil then table.insert(matches, { capture = c, metadata = metadata, lang = tree:lang() }) @@ -325,6 +326,12 @@ function M.get_captures_at_cursor(winnr) return captures end +--- @class vim.treesitter.GetNodeOpts +--- @field bufnr integer? +--- @field pos { [1]: integer, [2]: integer }? +--- @field lang string? +--- @field ignore_injections boolean? + --- Returns the smallest named node at the given position --- --- NOTE: Calling this on an unparsed tree can yield an invalid node. @@ -335,7 +342,7 @@ end --- vim.treesitter.get_parser(bufnr):parse(range) --- ``` --- ----@param opts table|nil Optional keyword arguments: +---@param opts vim.treesitter.GetNodeOpts? Optional keyword arguments: --- - bufnr integer|nil Buffer number (nil or 0 for current buffer) --- - pos table|nil 0-indexed (row, col) tuple. Defaults to cursor position in the --- current window. Required if {bufnr} is not the current buffer @@ -352,7 +359,7 @@ function M.get_node(opts) bufnr = api.nvim_get_current_buf() end - local row, col + local row, col --- @type integer, integer if opts.pos then assert(#opts.pos == 2, 'Position must be a (row, col) tuple') row, col = opts.pos[1], opts.pos[2] diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 08c4c2a832..99cc9bea09 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -7,7 +7,7 @@ local ns = api.nvim_create_namespace('treesitter/highlighter') ---@alias vim.treesitter.highlighter.Iter fun(end_line: integer|nil): integer, TSNode, TSMetadata ---@class vim.treesitter.highlighter.Query ----@field private _query vim.treesitter.query.Query? +---@field private _query vim.treesitter.Query? ---@field private lang string ---@field private hl_cache table local TSHighlighterQuery = {} diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua index 157b1461c3..b0e7ca1a35 100644 --- a/runtime/lua/vim/ui.lua +++ b/runtime/lua/vim/ui.lua @@ -20,7 +20,7 @@ local M = {} --- end) --- ``` --- ----@param items table Arbitrary items +---@param items any[] Arbitrary items ---@param opts table Additional options --- - prompt (string|nil) --- Text of the prompt. Defaults to `Select one of:` @@ -32,7 +32,7 @@ local M = {} --- Plugins reimplementing `vim.ui.select` may wish to --- use this to infer the structure or semantics of --- `items`, or the context in which select() was called. ----@param on_choice function ((item|nil, idx|nil) -> ()) +---@param on_choice fun(item: any|nil, idx: integer|nil) --- Called once the user made a choice. --- `idx` is the 1-based index of `item` within `items`. --- `nil` if the user aborted the dialog. @@ -44,7 +44,7 @@ function M.select(items, opts, on_choice) opts = opts or {} local choices = { opts.prompt or 'Select one of:' } local format_item = opts.format_item or tostring - for i, item in pairs(items) do + for i, item in ipairs(items) do table.insert(choices, string.format('%d: %s', i, format_item(item))) end local choice = vim.fn.inputlist(choices) @@ -66,7 +66,7 @@ end --- end) --- ``` --- ----@param opts table Additional options. See |input()| +---@param opts table? Additional options. See |input()| --- - prompt (string|nil) --- Text of the prompt --- - default (string|nil) @@ -87,6 +87,7 @@ end --- `nil` if the user aborted the dialog. function M.input(opts, on_confirm) vim.validate({ + opts = { opts, 'table', true }, on_confirm = { on_confirm, 'function', false }, }) diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua index 4f52938c6e..58c2a2386d 100644 --- a/runtime/lua/vim/version.lua +++ b/runtime/lua/vim/version.lua @@ -69,6 +69,8 @@ Version.__index = Version --- Compares prerelease strings: per semver, number parts must be must be treated as numbers: --- "pre1.10" is greater than "pre1.2". https://semver.org/#spec-item-11 +---@param prerel1 string? +---@param prerel2 string? local function cmp_prerel(prerel1, prerel2) if not prerel1 or not prerel2 then return prerel1 and -1 or (prerel2 and 1 or 0) @@ -78,8 +80,8 @@ local function cmp_prerel(prerel1, prerel2) local iter1 = prerel1:gmatch('([^0-9]*)(%d*)') local iter2 = prerel2:gmatch('([^0-9]*)(%d*)') while true do - local word1, n1 = iter1() - local word2, n2 = iter2() + local word1, n1 = iter1() --- @type string?, string|number|nil + local word2, n2 = iter2() --- @type string?, string|number|nil if word1 == nil and word2 == nil then -- Done iterating. return 0 end @@ -168,6 +170,7 @@ function M._version(version, strict) -- Adapted from https://github.com/folke/la end if not strict then -- TODO: add more "scrubbing". + --- @cast version string version = version:match('%d[^ ]*') end @@ -298,8 +301,9 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim local semver = M.parse(version) if semver then - local from = semver - local to = vim.deepcopy(semver, true) + local from = semver --- @type Version? + local to = vim.deepcopy(semver, true) --- @type Version? + ---@diagnostic disable: need-check-nil if mods == '' or mods == '=' then to.patch = to.patch + 1 elseif mods == '<' then @@ -309,9 +313,9 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim to.patch = to.patch + 1 elseif mods == '>' then from.patch = from.patch + 1 - to = nil ---@diagnostic disable-line: cast-local-type + to = nil elseif mods == '>=' then - to = nil ---@diagnostic disable-line: cast-local-type + to = nil elseif mods == '~' then if #parts >= 2 then to[2] = to[2] + 1 @@ -332,6 +336,7 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim end end end + ---@diagnostic enable: need-check-nil return setmetatable({ from = from, to = to }, { __index = VersionRange }) end end @@ -445,7 +450,7 @@ setmetatable(M, { --- Returns the current Nvim version. ---@return Version __call = function() - local version = vim.fn.api_info().version + local version = vim.fn.api_info().version ---@type Version -- Workaround: vim.fn.api_info().version reports "prerelease" as a boolean. version.prerelease = version.prerelease and 'dev' or nil return setmetatable(version, Version) -- cgit From a8e4ee2f2b4392e959b31c1d079166e245a401ba Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Mon, 26 Feb 2024 11:33:16 -0600 Subject: fix(defaults): validate 'channel' before responding to OSC request (#27594) Validate the channel number before responding to an OSC 10/11 request. When used with nvim_open_term, the channel number is unset (since there is no process on the other side of the PTY). --- runtime/lua/vim/_defaults.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 32534a89b4..7cece41ed3 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -143,6 +143,10 @@ do group = nvim_terminal_augroup, desc = 'Respond to OSC foreground/background color requests', callback = function(args) + local channel = vim.bo[args.buf].channel + if channel == 0 then + return + end local fg_request = args.data == '\027]10;?' local bg_request = args.data == '\027]11;?' if fg_request or bg_request then @@ -157,7 +161,6 @@ do end local command = fg_request and 10 or 11 local data = string.format('\027]%d;rgb:%04x/%04x/%04x\007', command, red, green, blue) - local channel = vim.bo[args.buf].channel vim.api.nvim_chan_send(channel, data) end end, -- cgit From 7ad2e3c64562bfb0ea2f7be305e4b0e6d2474d64 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Tue, 27 Feb 2024 03:53:49 -0800 Subject: docs: fix type of setreg() argument {options} (#27631) --- runtime/lua/vim/_meta/vimfn.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 07e6d42e1c..779016f2d1 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -8172,7 +8172,7 @@ function vim.fn.setqflist(list, action, what) end --- --- @param regname string --- @param value any ---- @param options? table +--- @param options? string --- @return any function vim.fn.setreg(regname, value, options) end -- cgit From 9beb40a4db5613601fc1a4b828a44e5977eca046 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 15 Feb 2024 17:16:04 +0000 Subject: feat(docs): replace lua2dox.lua Problem: The documentation flow (`gen_vimdoc.py`) has several issues: - it's not very versatile - depends on doxygen - doesn't work well with Lua code as it requires an awkward filter script to convert it into pseudo-C. - The intermediate XML files and filters makes it too much like a rube goldberg machine. Solution: Re-implement the flow using Lua, LPEG and treesitter. - `gen_vimdoc.py` is now replaced with `gen_vimdoc.lua` and replicates a portion of the logic. - `lua2dox.lua` is gone! - No more XML files. - Doxygen is now longer used and instead we now use: - LPEG for comment parsing (see `scripts/luacats_grammar.lua` and `scripts/cdoc_grammar.lua`). - LPEG for C parsing (see `scripts/cdoc_parser.lua`) - Lua patterns for Lua parsing (see `scripts/luacats_parser.lua`). - Treesitter for Markdown parsing (see `scripts/text_utils.lua`). - The generated `runtime/doc/*.mpack` files have been removed. - `scripts/gen_eval_files.lua` now instead uses `scripts/cdoc_parser.lua` directly. - Text wrapping is implemented in `scripts/text_utils.lua` and appears to produce more consistent results (the main contributer to the diff of this change). --- runtime/lua/vim/_editor.lua | 14 +- runtime/lua/vim/_inspector.lua | 4 +- runtime/lua/vim/_meta/api.lua | 843 +++++++++++++++------------ runtime/lua/vim/_meta/builtin.lua | 116 ++-- runtime/lua/vim/_meta/json.lua | 2 +- runtime/lua/vim/_meta/lpeg.lua | 23 +- runtime/lua/vim/_meta/mpack.lua | 5 +- runtime/lua/vim/_meta/re.lua | 13 +- runtime/lua/vim/_meta/regex.lua | 2 - runtime/lua/vim/_options.lua | 356 ++++++----- runtime/lua/vim/diagnostic.lua | 125 ++-- runtime/lua/vim/filetype.lua | 6 +- runtime/lua/vim/fs.lua | 2 +- runtime/lua/vim/highlight.lua | 15 +- runtime/lua/vim/iter.lua | 8 +- runtime/lua/vim/keymap.lua | 2 + runtime/lua/vim/loader.lua | 13 +- runtime/lua/vim/lsp.lua | 190 +++--- runtime/lua/vim/lsp/buf.lua | 35 +- runtime/lua/vim/lsp/codelens.lua | 2 + runtime/lua/vim/lsp/diagnostic.lua | 4 +- runtime/lua/vim/lsp/handlers.lua | 5 +- runtime/lua/vim/lsp/log.lua | 2 +- runtime/lua/vim/lsp/rpc.lua | 2 - runtime/lua/vim/lsp/sync.lua | 4 +- runtime/lua/vim/lsp/util.lua | 8 +- runtime/lua/vim/shared.lua | 92 +-- runtime/lua/vim/snippet.lua | 2 - runtime/lua/vim/treesitter.lua | 2 +- runtime/lua/vim/treesitter/_query_linter.lua | 2 +- runtime/lua/vim/treesitter/highlighter.lua | 1 - runtime/lua/vim/treesitter/languagetree.lua | 4 +- runtime/lua/vim/treesitter/query.lua | 4 +- runtime/lua/vim/uri.lua | 3 +- runtime/lua/vim/version.lua | 9 +- 35 files changed, 1009 insertions(+), 911 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index c5a6e65e86..4e39abb2be 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -127,10 +127,10 @@ vim.log = { --- timeout the process is sent the KILL signal (9) and the exit code is set to 124. Cannot --- be called in |api-fast|. --- - SystemCompleted is an object with the fields: ---- - code: (integer) ---- - signal: (integer) ---- - stdout: (string), nil if stdout argument is passed ---- - stderr: (string), nil if stderr argument is passed +--- - code: (integer) +--- - signal: (integer) +--- - stdout: (string), nil if stdout argument is passed +--- - stderr: (string), nil if stderr argument is passed --- - kill (fun(signal: integer|string)) --- - write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to close the stream. --- - is_closing (fun(): boolean) @@ -706,8 +706,8 @@ end --- Generates a list of possible completions for the string. --- String has the pattern. --- ---- 1. Can we get it to just return things in the global namespace with that name prefix ---- 2. Can we get it to return things from global namespace even with `print(` in front. +--- 1. Can we get it to just return things in the global namespace with that name prefix +--- 2. Can we get it to return things from global namespace even with `print(` in front. --- --- @param pat string function vim._expand_pat(pat, env) @@ -885,6 +885,7 @@ do --- similar to the builtin completion for the `:lua` command. --- --- Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a Lua buffer. + --- @param find_start 1|0 function vim.lua_omnifunc(find_start, _) if find_start == 1 then local line = vim.api.nvim_get_current_line() @@ -914,6 +915,7 @@ end --- --- @see |vim.inspect()| --- @see |:=| +--- @param ... any --- @return any # given arguments. function vim.print(...) if vim.in_fast_event() then diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua index 3f7b9d2c23..9a073c32c4 100644 --- a/runtime/lua/vim/_inspector.lua +++ b/runtime/lua/vim/_inspector.lua @@ -17,7 +17,7 @@ local defaults = { ---@param bufnr? integer defaults to the current buffer ---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor ---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor ----@param filter? InspectorFilter (table|nil) a table with key-value pairs to filter the items +---@param filter? InspectorFilter (table) a table with key-value pairs to filter the items --- - syntax (boolean): include syntax based highlight groups (defaults to true) --- - treesitter (boolean): include treesitter based highlight groups (defaults to true) --- - extmarks (boolean|"all"): include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true) @@ -139,7 +139,7 @@ end ---@param bufnr? integer defaults to the current buffer ---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor ---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor ----@param filter? InspectorFilter (table|nil) see |vim.inspect_pos()| +---@param filter? InspectorFilter (table) see |vim.inspect_pos()| function vim.show_pos(bufnr, row, col, filter) local items = vim.inspect_pos(bufnr, row, col, filter) diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index aee866f324..d2f624fd97 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -38,6 +38,7 @@ function vim.api.nvim__get_runtime(pat, all, opts) end --- @private --- Returns object given as argument. +--- --- This API function is used for testing. One should not rely on its presence --- in plugins. --- @@ -47,6 +48,7 @@ function vim.api.nvim__id(obj) end --- @private --- Returns array given as argument. +--- --- This API function is used for testing. One should not rely on its presence --- in plugins. --- @@ -56,6 +58,7 @@ function vim.api.nvim__id_array(arr) end --- @private --- Returns dictionary given as argument. +--- --- This API function is used for testing. One should not rely on its presence --- in plugins. --- @@ -65,6 +68,7 @@ function vim.api.nvim__id_dictionary(dct) end --- @private --- Returns floating-point value given as argument. +--- --- This API function is used for testing. One should not rely on its presence --- in plugins. --- @@ -108,17 +112,20 @@ function vim.api.nvim__stats() end function vim.api.nvim__unpack(str) end --- Adds a highlight to buffer. +--- --- Useful for plugins that dynamically generate highlights to a buffer (like --- a semantic highlighter or linter). The function adds a single highlight to --- a buffer. Unlike `matchaddpos()` highlights follow changes to line --- numbering (as lines are inserted/removed above the highlighted line), like --- signs and marks do. +--- --- Namespaces are used for batch deletion/updating of a set of highlights. To --- create a namespace, use `nvim_create_namespace()` which returns a --- namespace id. Pass it in to this function as `ns_id` to add highlights to --- the namespace. All highlights in the same namespace can then be cleared --- with single call to `nvim_buf_clear_namespace()`. If the highlight never --- will be deleted by an API call, pass `ns_id = -1`. +--- --- As a shorthand, `ns_id = 0` can be used to create a new namespace for the --- highlight, the allocated id is then returned. If `hl_group` is the empty --- string no highlight is added, but a new `ns_id` is still returned. This is @@ -131,11 +138,12 @@ function vim.api.nvim__unpack(str) end --- @param line integer Line to highlight (zero-indexed) --- @param col_start integer Start of (byte-indexed) column range to highlight --- @param col_end integer End of (byte-indexed) column range to highlight, or -1 to ---- highlight to end of line +--- highlight to end of line --- @return integer function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start, col_end) end --- Activates buffer-update events on a channel, or as Lua callbacks. +--- --- Example (Lua): capture buffer updates in a global `events` variable (use --- "vim.print(events)" to see its contents): --- @@ -148,6 +156,7 @@ function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start --- }) --- ``` --- +--- --- @param buffer integer Buffer handle, or 0 for current buffer --- @param send_buffer boolean True if the initial notification should contain the --- whole buffer: first notification will be @@ -155,77 +164,70 @@ function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start --- will be `nvim_buf_changedtick_event`. Not for Lua --- callbacks. --- @param opts vim.api.keyset.buf_attach Optional parameters. ---- • on_lines: Lua callback invoked on change. Return a ---- truthy value (not `false` or `nil`) ---- to detach. Args: ---- • the string "lines" ---- • buffer handle ---- • b:changedtick ---- • first line that changed (zero-indexed) ---- • last line that was changed ---- • last line in the updated range ---- • byte count of previous contents ---- • deleted_codepoints (if `utf_sizes` is true) ---- • deleted_codeunits (if `utf_sizes` is true) ---- ---- • on_bytes: Lua callback invoked on change. This ---- callback receives more granular information about the ---- change compared to on_lines. Return a truthy value ---- (not `false` or `nil`) to ---- detach. Args: ---- • the string "bytes" ---- • buffer handle ---- • b:changedtick ---- • start row of the changed text (zero-indexed) ---- • start column of the changed text ---- • byte offset of the changed text (from the start of ---- the buffer) ---- • old end row of the changed text (offset from start ---- row) ---- • old end column of the changed text (if old end row ---- = 0, offset from start column) ---- • old end byte length of the changed text ---- • new end row of the changed text (offset from start ---- row) ---- • new end column of the changed text (if new end row ---- = 0, offset from start column) ---- • new end byte length of the changed text ---- ---- • on_changedtick: Lua callback invoked on changedtick ---- increment without text change. Args: ---- • the string "changedtick" ---- • buffer handle ---- • b:changedtick ---- ---- • on_detach: Lua callback invoked on detach. Args: ---- • the string "detach" ---- • buffer handle ---- ---- • on_reload: Lua callback invoked on reload. The entire ---- buffer content should be considered changed. Args: ---- • the string "reload" ---- • buffer handle ---- ---- • utf_sizes: include UTF-32 and UTF-16 size of the ---- replaced region, as args to `on_lines`. ---- • preview: also attach to command preview (i.e. ---- 'inccommand') events. +--- • on_lines: Lua callback invoked on change. Return a truthy +--- value (not `false` or `nil`) to detach. Args: +--- • the string "lines" +--- • buffer handle +--- • b:changedtick +--- • first line that changed (zero-indexed) +--- • last line that was changed +--- • last line in the updated range +--- • byte count of previous contents +--- • deleted_codepoints (if `utf_sizes` is true) +--- • deleted_codeunits (if `utf_sizes` is true) +--- • on_bytes: Lua callback invoked on change. This callback +--- receives more granular information about the change compared +--- to on_lines. Return a truthy value (not `false` or `nil`) to +--- detach. Args: +--- • the string "bytes" +--- • buffer handle +--- • b:changedtick +--- • start row of the changed text (zero-indexed) +--- • start column of the changed text +--- • byte offset of the changed text (from the start of the +--- buffer) +--- • old end row of the changed text (offset from start row) +--- • old end column of the changed text (if old end row = 0, +--- offset from start column) +--- • old end byte length of the changed text +--- • new end row of the changed text (offset from start row) +--- • new end column of the changed text (if new end row = 0, +--- offset from start column) +--- • new end byte length of the changed text +--- • on_changedtick: Lua callback invoked on changedtick +--- increment without text change. Args: +--- • the string "changedtick" +--- • buffer handle +--- • b:changedtick +--- • on_detach: Lua callback invoked on detach. Args: +--- • the string "detach" +--- • buffer handle +--- • on_reload: Lua callback invoked on reload. The entire buffer +--- content should be considered changed. Args: +--- • the string "reload" +--- • buffer handle +--- • utf_sizes: include UTF-32 and UTF-16 size of the replaced +--- region, as args to `on_lines`. +--- • preview: also attach to command preview (i.e. 'inccommand') +--- events. --- @return boolean function vim.api.nvim_buf_attach(buffer, send_buffer, opts) end --- call a function with buffer as temporary current buffer +--- --- This temporarily switches current buffer to "buffer". If the current --- window already shows "buffer", the window is not switched If a window --- inside the current tabpage (including a float) already shows the buffer --- One of these windows will be set as current window temporarily. Otherwise --- a temporary scratch window (called the "autocmd window" for historical --- reasons) will be used. +--- --- This is useful e.g. to call Vimscript functions that only work with the --- current buffer/window currently, like `termopen()`. --- --- @param buffer integer Buffer handle, or 0 for current buffer --- @param fun function Function to call inside the buffer (currently Lua callable ---- only) +--- only) --- @return any function vim.api.nvim_buf_call(buffer, fun) end @@ -238,14 +240,15 @@ function vim.api.nvim_buf_clear_highlight(buffer, ns_id, line_start, line_end) e --- Clears `namespace`d objects (highlights, `extmarks`, virtual text) from a --- region. +--- --- Lines are 0-indexed. `api-indexing` To clear the namespace in the entire --- buffer, specify line_start=0 and line_end=-1. --- --- @param buffer integer Buffer handle, or 0 for current buffer --- @param ns_id integer Namespace to clear, or -1 to clear all namespaces. --- @param line_start integer Start of range of lines to clear ---- @param line_end integer End of range of lines to clear (exclusive) or -1 to ---- clear to end of buffer. +--- @param line_end integer End of range of lines to clear (exclusive) or -1 to clear +--- to end of buffer. function vim.api.nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end) end --- Creates a buffer-local command `user-commands`. @@ -279,6 +282,7 @@ function vim.api.nvim_buf_del_keymap(buffer, mode, lhs) end function vim.api.nvim_buf_del_mark(buffer, name) end --- Delete a buffer-local user-defined command. +--- --- Only commands created with `:command-buffer` or --- `nvim_buf_create_user_command()` can be deleted with this function. --- @@ -296,8 +300,8 @@ function vim.api.nvim_buf_del_var(buffer, name) end --- --- @param buffer integer Buffer handle, or 0 for current buffer --- @param opts vim.api.keyset.buf_delete Optional parameters. Keys: ---- • force: Force deletion and ignore unsaved changes. ---- • unload: Unloaded only, do not delete. See `:bunload` +--- • force: Force deletion and ignore unsaved changes. +--- • unload: Unloaded only, do not delete. See `:bunload` function vim.api.nvim_buf_delete(buffer, opts) end --- Gets a changed tick of a buffer @@ -319,14 +323,15 @@ function vim.api.nvim_buf_get_commands(buffer, opts) end --- @param ns_id integer Namespace id from `nvim_create_namespace()` --- @param id integer Extmark id --- @param opts vim.api.keyset.get_extmark Optional parameters. Keys: ---- • details: Whether to include the details dict ---- • hl_name: Whether to include highlight group name instead ---- of id, true if omitted +--- • details: Whether to include the details dict +--- • hl_name: Whether to include highlight group name instead of +--- id, true if omitted --- @return vim.api.keyset.get_extmark_item function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end --- Gets `extmarks` in "traversal order" from a `charwise` region defined by --- buffer positions (inclusive, 0-indexed `api-indexing`). +--- --- Region can be given as (row,col) tuples, or valid extmark ids (whose --- positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1) --- respectively, thus the following are equivalent: @@ -338,12 +343,15 @@ function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end --- --- If `end` is less than `start`, traversal works backwards. (Useful with --- `limit`, to get the first marks prior to a given position.) +--- --- Note: when using extmark ranges (marks with a end_row/end_col position) --- the `overlap` option might be useful. Otherwise only the start position of --- an extmark will be considered. +--- --- Note: legacy signs placed through the `:sign` commands are implemented as --- extmarks and will show up here. Their details array will contain a --- `sign_name` field. +--- --- Example: --- --- ```lua @@ -361,23 +369,23 @@ function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end --- vim.print(ms) --- ``` --- +--- --- @param buffer integer Buffer handle, or 0 for current buffer --- @param ns_id integer Namespace id from `nvim_create_namespace()` or -1 for all ---- namespaces +--- namespaces --- @param start any Start of range: a 0-indexed (row, col) or valid extmark id ---- (whose position defines the bound). `api-indexing` +--- (whose position defines the bound). `api-indexing` --- @param end_ any End of range (inclusive): a 0-indexed (row, col) or valid ---- extmark id (whose position defines the bound). ---- `api-indexing` +--- extmark id (whose position defines the bound). `api-indexing` --- @param opts vim.api.keyset.get_extmarks Optional parameters. Keys: ---- • limit: Maximum number of marks to return ---- • details: Whether to include the details dict ---- • hl_name: Whether to include highlight group name instead ---- of id, true if omitted ---- • overlap: Also include marks which overlap the range, even ---- if their start position is less than `start` ---- • type: Filter marks by type: "highlight", "sign", ---- "virt_text" and "virt_lines" +--- • limit: Maximum number of marks to return +--- • details: Whether to include the details dict +--- • hl_name: Whether to include highlight group name instead of +--- id, true if omitted +--- • overlap: Also include marks which overlap the range, even if +--- their start position is less than `start` +--- • type: Filter marks by type: "highlight", "sign", "virt_text" +--- and "virt_lines" --- @return vim.api.keyset.get_extmark_item[] function vim.api.nvim_buf_get_extmarks(buffer, ns_id, start, end_, opts) end @@ -389,9 +397,11 @@ function vim.api.nvim_buf_get_extmarks(buffer, ns_id, start, end_, opts) end function vim.api.nvim_buf_get_keymap(buffer, mode) end --- Gets a line-range from the buffer. +--- --- Indexing is zero-based, end-exclusive. Negative indices are interpreted as --- length+1+index: -1 refers to the index past the end. So to get the last --- element use start=-2 and end=-1. +--- --- Out-of-bounds indices are clamped to the nearest valid value, unless --- `strict_indexing` is set. --- @@ -405,6 +415,7 @@ function vim.api.nvim_buf_get_lines(buffer, start, end_, strict_indexing) end --- Returns a `(row,col)` tuple representing the position of the named mark. --- "End of line" column position is returned as `v:maxcol` (big number). See --- `mark-motions`. +--- --- Marks are (1,0)-indexed. `api-indexing` --- --- @param buffer integer Buffer handle, or 0 for current buffer @@ -424,10 +435,12 @@ function vim.api.nvim_buf_get_name(buffer) end function vim.api.nvim_buf_get_number(buffer) end --- Returns the byte offset of a line (0-indexed). `api-indexing` +--- --- Line 1 (index=0) has offset 0. UTF-8 bytes are counted. EOL is one byte. --- 'fileformat' and 'fileencoding' are ignored. The line index just after the --- last line gives the total byte-count of the buffer. A final EOL byte is --- counted if it would be written, see 'eol'. +--- --- Unlike `line2byte()`, throws error for out-of-bounds indexing. Returns -1 --- for unloaded buffer. --- @@ -443,10 +456,13 @@ function vim.api.nvim_buf_get_offset(buffer, index) end function vim.api.nvim_buf_get_option(buffer, name) end --- Gets a range from the buffer. +--- --- This differs from `nvim_buf_get_lines()` in that it allows retrieving only --- portions of a line. +--- --- Indexing is zero-based. Row indices are end-inclusive, and column indices --- are end-exclusive. +--- --- Prefer `nvim_buf_get_lines()` when retrieving entire lines. --- --- @param buffer integer Buffer handle, or 0 for current buffer @@ -485,13 +501,16 @@ function vim.api.nvim_buf_is_valid(buffer) end function vim.api.nvim_buf_line_count(buffer) end --- Creates or updates an `extmark`. +--- --- By default a new extmark is created when no id is passed in, but it is --- also possible to create a new mark by passing in a previously unused id or --- move an existing mark by passing in its id. The caller must then keep --- track of existing and unused ids itself. (Useful over RPC, to avoid --- waiting for the return value.) +--- --- Using the optional arguments, it is possible to use this to highlight a --- range of text, and also to associate virtual text to the mark. +--- --- If present, the position defined by `end_col` and `end_row` should be --- after the start position in order for the extmark to cover a range. An --- earlier end position is not an error, but then it behaves like an empty @@ -502,114 +521,110 @@ function vim.api.nvim_buf_line_count(buffer) end --- @param line integer Line where to place the mark, 0-based. `api-indexing` --- @param col integer Column where to place the mark, 0-based. `api-indexing` --- @param opts vim.api.keyset.set_extmark Optional parameters. ---- • id : id of the extmark to edit. ---- • end_row : ending line of the mark, 0-based inclusive. ---- • end_col : ending col of the mark, 0-based exclusive. ---- • hl_group : name of the highlight group used to highlight ---- this mark. ---- • hl_eol : when true, for a multiline highlight covering the ---- EOL of a line, continue the highlight for the rest of the ---- screen line (just like for diff and cursorline highlight). ---- • virt_text : virtual text to link to this mark. A list of ---- [text, highlight] tuples, each representing a text chunk ---- with specified highlight. `highlight` element can either ---- be a single highlight group, or an array of multiple ---- highlight groups that will be stacked (highest priority ---- last). A highlight group can be supplied either as a ---- string or as an integer, the latter which can be obtained ---- using `nvim_get_hl_id_by_name()`. ---- • virt_text_pos : position of virtual text. Possible values: ---- • "eol": right after eol character (default). ---- • "overlay": display over the specified column, without ---- shifting the underlying text. ---- • "right_align": display right aligned in the window. ---- • "inline": display at the specified column, and shift the ---- buffer text to the right as needed. ---- ---- • virt_text_win_col : position the virtual text at a fixed ---- window column (starting from the first text column of the ---- screen line) instead of "virt_text_pos". ---- • virt_text_hide : hide the virtual text when the background ---- text is selected or hidden because of scrolling with ---- 'nowrap' or 'smoothscroll'. Currently only affects ---- "overlay" virt_text. ---- • virt_text_repeat_linebreak : repeat the virtual text on ---- wrapped lines. ---- • hl_mode : control how highlights are combined with the ---- highlights of the text. Currently only affects virt_text ---- highlights, but might affect `hl_group` in ---- later versions. ---- • "replace": only show the virt_text color. This is the ---- default. ---- • "combine": combine with background text color. ---- • "blend": blend with background text color. Not supported ---- for "inline" virt_text. ---- ---- • virt_lines : virtual lines to add next to this mark This ---- should be an array over lines, where each line in turn is ---- an array over [text, highlight] tuples. In general, buffer ---- and window options do not affect the display of the text. ---- In particular 'wrap' and 'linebreak' options do not take ---- effect, so the number of extra screen lines will always ---- match the size of the array. However the 'tabstop' buffer ---- option is still used for hard tabs. By default lines are ---- placed below the buffer line containing the mark. ---- • virt_lines_above: place virtual lines above instead. ---- • virt_lines_leftcol: Place extmarks in the leftmost column ---- of the window, bypassing sign and number columns. ---- • ephemeral : for use with `nvim_set_decoration_provider()` ---- callbacks. The mark will only be used for the current ---- redraw cycle, and not be permantently stored in the ---- buffer. ---- • right_gravity : boolean that indicates the direction the ---- extmark will be shifted in when new text is inserted (true ---- for right, false for left). Defaults to true. ---- • end_right_gravity : boolean that indicates the direction ---- the extmark end position (if it exists) will be shifted in ---- when new text is inserted (true for right, false for ---- left). Defaults to false. ---- • undo_restore : Restore the exact position of the mark if ---- text around the mark was deleted and then restored by ---- undo. Defaults to true. ---- • invalidate : boolean that indicates whether to hide the ---- extmark if the entirety of its range is deleted. For ---- hidden marks, an "invalid" key is added to the "details" ---- array of `nvim_buf_get_extmarks()` and family. If ---- "undo_restore" is false, the extmark is deleted instead. ---- • priority: a priority value for the highlight group, sign ---- attribute or virtual text. For virtual text, item with ---- highest priority is drawn last. For example treesitter ---- highlighting uses a value of 100. ---- • strict: boolean that indicates extmark should not be ---- placed if the line or column value is past the end of the ---- buffer or end of the line respectively. Defaults to true. ---- • sign_text: string of length 1-2 used to display in the ---- sign column. ---- • sign_hl_group: name of the highlight group used to ---- highlight the sign column text. ---- • number_hl_group: name of the highlight group used to ---- highlight the number column. ---- • line_hl_group: name of the highlight group used to ---- highlight the whole line. ---- • cursorline_hl_group: name of the highlight group used to ---- highlight the sign column text when the cursor is on the ---- same line as the mark and 'cursorline' is enabled. ---- • conceal: string which should be either empty or a single ---- character. Enable concealing similar to `:syn-conceal`. ---- When a character is supplied it is used as `:syn-cchar`. ---- "hl_group" is used as highlight for the cchar if provided, ---- otherwise it defaults to `hl-Conceal`. ---- • spell: boolean indicating that spell checking should be ---- performed within this extmark ---- • ui_watched: boolean that indicates the mark should be ---- drawn by a UI. When set, the UI will receive win_extmark ---- events. Note: the mark is positioned by virt_text ---- attributes. Can be used together with virt_text. ---- • url: A URL to associate with this extmark. In the TUI, the ---- OSC 8 control sequence is used to generate a clickable ---- hyperlink to this URL. ---- • scoped: boolean that indicates that the extmark should ---- only be displayed in the namespace scope. (experimental) +--- • id : id of the extmark to edit. +--- • end_row : ending line of the mark, 0-based inclusive. +--- • end_col : ending col of the mark, 0-based exclusive. +--- • hl_group : name of the highlight group used to highlight +--- this mark. +--- • hl_eol : when true, for a multiline highlight covering the +--- EOL of a line, continue the highlight for the rest of the +--- screen line (just like for diff and cursorline highlight). +--- • virt_text : virtual text to link to this mark. A list of +--- [text, highlight] tuples, each representing a text chunk +--- with specified highlight. `highlight` element can either be +--- a single highlight group, or an array of multiple highlight +--- groups that will be stacked (highest priority last). A +--- highlight group can be supplied either as a string or as an +--- integer, the latter which can be obtained using +--- `nvim_get_hl_id_by_name()`. +--- • virt_text_pos : position of virtual text. Possible values: +--- • "eol": right after eol character (default). +--- • "overlay": display over the specified column, without +--- shifting the underlying text. +--- • "right_align": display right aligned in the window. +--- • "inline": display at the specified column, and shift the +--- buffer text to the right as needed. +--- • virt_text_win_col : position the virtual text at a fixed +--- window column (starting from the first text column of the +--- screen line) instead of "virt_text_pos". +--- • virt_text_hide : hide the virtual text when the background +--- text is selected or hidden because of scrolling with +--- 'nowrap' or 'smoothscroll'. Currently only affects "overlay" +--- virt_text. +--- • virt_text_repeat_linebreak : repeat the virtual text on +--- wrapped lines. +--- • hl_mode : control how highlights are combined with the +--- highlights of the text. Currently only affects virt_text +--- highlights, but might affect `hl_group` in later versions. +--- • "replace": only show the virt_text color. This is the +--- default. +--- • "combine": combine with background text color. +--- • "blend": blend with background text color. Not supported +--- for "inline" virt_text. +--- • virt_lines : virtual lines to add next to this mark This +--- should be an array over lines, where each line in turn is an +--- array over [text, highlight] tuples. In general, buffer and +--- window options do not affect the display of the text. In +--- particular 'wrap' and 'linebreak' options do not take +--- effect, so the number of extra screen lines will always +--- match the size of the array. However the 'tabstop' buffer +--- option is still used for hard tabs. By default lines are +--- placed below the buffer line containing the mark. +--- • virt_lines_above: place virtual lines above instead. +--- • virt_lines_leftcol: Place extmarks in the leftmost column of +--- the window, bypassing sign and number columns. +--- • ephemeral : for use with `nvim_set_decoration_provider()` +--- callbacks. The mark will only be used for the current redraw +--- cycle, and not be permantently stored in the buffer. +--- • right_gravity : boolean that indicates the direction the +--- extmark will be shifted in when new text is inserted (true +--- for right, false for left). Defaults to true. +--- • end_right_gravity : boolean that indicates the direction the +--- extmark end position (if it exists) will be shifted in when +--- new text is inserted (true for right, false for left). +--- Defaults to false. +--- • undo_restore : Restore the exact position of the mark if +--- text around the mark was deleted and then restored by undo. +--- Defaults to true. +--- • invalidate : boolean that indicates whether to hide the +--- extmark if the entirety of its range is deleted. For hidden +--- marks, an "invalid" key is added to the "details" array of +--- `nvim_buf_get_extmarks()` and family. If "undo_restore" is +--- false, the extmark is deleted instead. +--- • priority: a priority value for the highlight group, sign +--- attribute or virtual text. For virtual text, item with +--- highest priority is drawn last. For example treesitter +--- highlighting uses a value of 100. +--- • strict: boolean that indicates extmark should not be placed +--- if the line or column value is past the end of the buffer or +--- end of the line respectively. Defaults to true. +--- • sign_text: string of length 1-2 used to display in the sign +--- column. +--- • sign_hl_group: name of the highlight group used to highlight +--- the sign column text. +--- • number_hl_group: name of the highlight group used to +--- highlight the number column. +--- • line_hl_group: name of the highlight group used to highlight +--- the whole line. +--- • cursorline_hl_group: name of the highlight group used to +--- highlight the sign column text when the cursor is on the +--- same line as the mark and 'cursorline' is enabled. +--- • conceal: string which should be either empty or a single +--- character. Enable concealing similar to `:syn-conceal`. When +--- a character is supplied it is used as `:syn-cchar`. +--- "hl_group" is used as highlight for the cchar if provided, +--- otherwise it defaults to `hl-Conceal`. +--- • spell: boolean indicating that spell checking should be +--- performed within this extmark +--- • ui_watched: boolean that indicates the mark should be drawn +--- by a UI. When set, the UI will receive win_extmark events. +--- Note: the mark is positioned by virt_text attributes. Can be +--- used together with virt_text. +--- • url: A URL to associate with this extmark. In the TUI, the +--- OSC 8 control sequence is used to generate a clickable +--- hyperlink to this URL. +--- • scoped: boolean that indicates that the extmark should only +--- be displayed in the namespace scope. (experimental) --- @return integer function vim.api.nvim_buf_set_extmark(buffer, ns_id, line, col, opts) end @@ -623,11 +638,14 @@ function vim.api.nvim_buf_set_extmark(buffer, ns_id, line, col, opts) end function vim.api.nvim_buf_set_keymap(buffer, mode, lhs, rhs, opts) end --- Sets (replaces) a line-range in the buffer. +--- --- Indexing is zero-based, end-exclusive. Negative indices are interpreted as --- length+1+index: -1 refers to the index past the end. So to change or --- delete the last element use start=-2 and end=-1. +--- --- To insert lines at a given index, set `start` and `end` to the same index. --- To delete a range of lines, set `replacement` to an empty array. +--- --- Out-of-bounds indices are clamped to the nearest valid value, unless --- `strict_indexing` is set. --- @@ -640,6 +658,7 @@ function vim.api.nvim_buf_set_lines(buffer, start, end_, strict_indexing, replac --- Sets a named mark in the given buffer, all marks are allowed --- file/uppercase, visual, last change, etc. See `mark-motions`. +--- --- Marks are (1,0)-indexed. `api-indexing` --- --- @param buffer integer Buffer to set the mark on @@ -663,16 +682,21 @@ function vim.api.nvim_buf_set_name(buffer, name) end function vim.api.nvim_buf_set_option(buffer, name, value) end --- Sets (replaces) a range in the buffer +--- --- This is recommended over `nvim_buf_set_lines()` when only modifying parts --- of a line, as extmarks will be preserved on non-modified parts of the --- touched lines. +--- --- Indexing is zero-based. Row indices are end-inclusive, and column indices --- are end-exclusive. +--- --- To insert text at a given `(row, column)` location, use `start_row = --- end_row = row` and `start_col = end_col = col`. To delete the text in a --- range, use `replacement = {}`. +--- --- Prefer `nvim_buf_set_lines()` if you are only adding or deleting entire --- lines. +--- --- Prefer `nvim_put()` if you want to insert text at the cursor position. --- --- @param buffer integer Buffer handle, or 0 for current buffer @@ -700,6 +724,7 @@ function vim.api.nvim_buf_set_var(buffer, name, value) end function vim.api.nvim_buf_set_virtual_text(buffer, src_id, line, chunks, opts) end --- Calls a Vimscript `Dictionary-function` with the given arguments. +--- --- On execution error: fails with Vimscript error, updates v:errmsg. --- --- @param dict any Dictionary, or String evaluating to a Vimscript `self` dict @@ -709,6 +734,7 @@ function vim.api.nvim_buf_set_virtual_text(buffer, src_id, line, chunks, opts) e function vim.api.nvim_call_dict_function(dict, fn, args) end --- Calls a Vimscript function with the given arguments. +--- --- On execution error: fails with Vimscript error, updates v:errmsg. --- --- @param fn string Function to call @@ -720,6 +746,7 @@ function vim.api.nvim_call_function(fn, args) end --- process. For the stdio channel `channel-stdio`, it writes to Nvim's --- stdout. For an internal terminal instance (`nvim_open_term()`) it writes --- directly to terminal output. See `channel-bytes` for more information. +--- --- This function writes raw data, not RPC messages. If the channel was --- created with `rpc=true` then the channel expects RPC messages, use --- `vim.rpcnotify()` and `vim.rpcrequest()` instead. @@ -736,42 +763,41 @@ function vim.api.nvim_chan_send(chan, data) end --- • event: "pat1" --- • event: { "pat1" } --- • event: { "pat1", "pat2", "pat3" } ---- --- • pattern: (string|table) --- • pattern or patterns to match exactly. --- • For example, if you have `*.py` as that pattern for the --- autocmd, you must pass `*.py` exactly to clear it. --- `test.py` will not match the pattern. ---- --- • defaults to clearing all patterns. --- • NOTE: Cannot be used with {buffer} ---- --- • buffer: (bufnr) --- • clear only `autocmd-buflocal` autocommands. --- • NOTE: Cannot be used with {pattern} ---- --- • group: (string|int) The augroup name or id. --- • NOTE: If not passed, will only delete autocmds not in any --- group. function vim.api.nvim_clear_autocmds(opts) end --- Executes an Ex command. +--- --- Unlike `nvim_command()` this command takes a structured Dictionary instead --- of a String. This allows for easier construction and manipulation of an Ex --- command. This also allows for things such as having spaces inside a --- command argument, expanding filenames in a command that otherwise doesn't --- expand filenames, etc. Command arguments may also be Number, Boolean or --- String. +--- --- The first argument may also be used instead of count for commands that --- support it in order to make their usage simpler with `vim.cmd()`. For --- example, instead of `vim.cmd.bdelete{ count = 2 }`, you may do --- `vim.cmd.bdelete(2)`. +--- --- On execution error: fails with Vimscript error, updates v:errmsg. --- --- @param cmd vim.api.keyset.cmd Command to execute. Must be a Dictionary that can contain the ---- same values as the return value of `nvim_parse_cmd()` except ---- "addr", "nargs" and "nextcmd" which are ignored if provided. ---- All values except for "cmd" are optional. +--- same values as the return value of `nvim_parse_cmd()` except +--- "addr", "nargs" and "nextcmd" which are ignored if provided. +--- All values except for "cmd" are optional. --- @param opts vim.api.keyset.cmd_opts Optional parameters. --- • output: (boolean, default false) Whether to return command --- output. @@ -779,7 +805,9 @@ function vim.api.nvim_clear_autocmds(opts) end function vim.api.nvim_cmd(cmd, opts) end --- Executes an Ex command. +--- --- On execution error: fails with Vimscript error, updates v:errmsg. +--- --- Prefer using `nvim_cmd()` or `nvim_exec2()` over this. To evaluate --- multiple lines of Vim script or an Ex command directly, use --- `nvim_exec2()`. To construct an Ex command using a structured format and @@ -800,11 +828,12 @@ function vim.api.nvim_command_output(command) end --- --- @param index integer the completion candidate index --- @param opts vim.api.keyset.complete_set Optional parameters. ---- • info: (string) info text. +--- • info: (string) info text. --- @return table function vim.api.nvim_complete_set(index, opts) end --- Create or get an autocommand group `autocmd-groups`. +--- --- To get an existing group id, do: --- --- ```lua @@ -813,6 +842,7 @@ function vim.api.nvim_complete_set(index, opts) end --- }) --- ``` --- +--- --- @param name string String: The name of the group --- @param opts vim.api.keyset.create_augroup Dictionary Parameters --- • clear (bool) optional: defaults to true. Clear existing @@ -820,8 +850,10 @@ function vim.api.nvim_complete_set(index, opts) end --- @return integer function vim.api.nvim_create_augroup(name, opts) end ---- Creates an `autocommand` event handler, defined by `callback` (Lua function ---- or Vimscript function name string) or `command` (Ex command string). +--- Creates an `autocommand` event handler, defined by `callback` (Lua +--- function or Vimscript function name string) or `command` (Ex command +--- string). +--- --- Example using Lua callback: --- --- ```lua @@ -849,39 +881,39 @@ function vim.api.nvim_create_augroup(name, opts) end --- pattern = vim.fn.expand("~") .. "/some/path/*.py" --- ``` --- +--- --- @param event any (string|array) Event(s) that will trigger the handler --- (`callback` or `command`). --- @param opts vim.api.keyset.create_autocmd Options dict: ---- • group (string|integer) optional: autocommand group name or ---- id to match against. ---- • pattern (string|array) optional: pattern(s) to match ---- literally `autocmd-pattern`. ---- • buffer (integer) optional: buffer number for buffer-local ---- autocommands `autocmd-buflocal`. Cannot be used with ---- {pattern}. ---- • desc (string) optional: description (for documentation and ---- troubleshooting). ---- • callback (function|string) optional: Lua function (or ---- Vimscript function name, if string) called when the ---- event(s) is triggered. Lua callback can return a truthy ---- value (not `false` or `nil`) to delete the ---- autocommand. Receives a table argument with these keys: ---- • id: (number) autocommand id ---- • event: (string) name of the triggered event ---- `autocmd-events` ---- • group: (number|nil) autocommand group id, if any ---- • match: (string) expanded value of `` ---- • buf: (number) expanded value of `` ---- • file: (string) expanded value of `` ---- • data: (any) arbitrary data passed from ---- `nvim_exec_autocmds()` ---- ---- • command (string) optional: Vim command to execute on event. ---- Cannot be used with {callback} ---- • once (boolean) optional: defaults to false. Run the ---- autocommand only once `autocmd-once`. ---- • nested (boolean) optional: defaults to false. Run nested ---- autocommands `autocmd-nested`. +--- • group (string|integer) optional: autocommand group name or +--- id to match against. +--- • pattern (string|array) optional: pattern(s) to match +--- literally `autocmd-pattern`. +--- • buffer (integer) optional: buffer number for buffer-local +--- autocommands `autocmd-buflocal`. Cannot be used with +--- {pattern}. +--- • desc (string) optional: description (for documentation and +--- troubleshooting). +--- • callback (function|string) optional: Lua function (or +--- Vimscript function name, if string) called when the event(s) +--- is triggered. Lua callback can return a truthy value (not +--- `false` or `nil`) to delete the autocommand. Receives a +--- table argument with these keys: +--- • id: (number) autocommand id +--- • event: (string) name of the triggered event +--- `autocmd-events` +--- • group: (number|nil) autocommand group id, if any +--- • match: (string) expanded value of `` +--- • buf: (number) expanded value of `` +--- • file: (string) expanded value of `` +--- • data: (any) arbitrary data passed from +--- `nvim_exec_autocmds()` +--- • command (string) optional: Vim command to execute on event. +--- Cannot be used with {callback} +--- • once (boolean) optional: defaults to false. Run the +--- autocommand only once `autocmd-once`. +--- • nested (boolean) optional: defaults to false. Run nested +--- autocommands `autocmd-nested`. --- @return integer function vim.api.nvim_create_autocmd(event, opts) end @@ -894,9 +926,11 @@ function vim.api.nvim_create_autocmd(event, opts) end --- @return integer function vim.api.nvim_create_buf(listed, scratch) end ---- Creates a new namespace or gets an existing one. *namespace* +--- Creates a new namespace or gets an existing one. *namespace* +--- --- Namespaces are used for buffer highlights and virtual text, see --- `nvim_buf_add_highlight()` and `nvim_buf_set_extmark()`. +--- --- Namespaces can be named or anonymous. If `name` matches an existing --- namespace, the associated id is returned. If `name` is an empty string a --- new, anonymous namespace is created. @@ -906,7 +940,9 @@ function vim.api.nvim_create_buf(listed, scratch) end function vim.api.nvim_create_namespace(name) end --- Creates a global `user-commands` command. +--- --- For Lua usage see `lua-guide-commands-create`. +--- --- Example: --- --- ```vim @@ -915,8 +951,9 @@ function vim.api.nvim_create_namespace(name) end --- Hello world! --- ``` --- +--- --- @param name string Name of the new user command. Must begin with an uppercase ---- letter. +--- letter. --- @param command any Replacement command to execute when this user command is --- executed. When called from Lua, the command can also be a --- Lua function. The function is called with a single table @@ -943,23 +980,24 @@ function vim.api.nvim_create_namespace(name) end --- Has the same structure as the "mods" key of --- `nvim_parse_cmd()`. --- @param opts vim.api.keyset.user_command Optional `command-attributes`. ---- • Set boolean attributes such as `:command-bang` or ---- `:command-bar` to true (but not `:command-buffer`, use ---- `nvim_buf_create_user_command()` instead). ---- • "complete" `:command-complete` also accepts a Lua ---- function which works like ---- `:command-completion-customlist`. ---- • Other parameters: ---- • desc: (string) Used for listing the command when a Lua ---- function is used for {command}. ---- • force: (boolean, default true) Override any previous ---- definition. ---- • preview: (function) Preview callback for 'inccommand' ---- `:command-preview` +--- • Set boolean attributes such as `:command-bang` or +--- `:command-bar` to true (but not `:command-buffer`, use +--- `nvim_buf_create_user_command()` instead). +--- • "complete" `:command-complete` also accepts a Lua function +--- which works like `:command-completion-customlist`. +--- • Other parameters: +--- • desc: (string) Used for listing the command when a Lua +--- function is used for {command}. +--- • force: (boolean, default true) Override any previous +--- definition. +--- • preview: (function) Preview callback for 'inccommand' +--- `:command-preview` function vim.api.nvim_create_user_command(name, command, opts) end --- Delete an autocommand group by id. +--- --- To get a group id one can use `nvim_get_autocmds()`. +--- --- NOTE: behavior differs from `:augroup-delete`. When deleting a group, --- autocommands contained in this group will also be deleted and cleared. --- This group will no longer exist. @@ -968,6 +1006,7 @@ function vim.api.nvim_create_user_command(name, command, opts) end function vim.api.nvim_del_augroup_by_id(id) end --- Delete an autocommand group by name. +--- --- NOTE: behavior differs from `:augroup-delete`. When deleting a group, --- autocommands contained in this group will also be deleted and cleared. --- This group will no longer exist. @@ -985,6 +1024,7 @@ function vim.api.nvim_del_autocmd(id) end function vim.api.nvim_del_current_line() end --- Unmaps a global `mapping` for the given mode. +--- --- To unmap a buffer-local mapping, use `nvim_buf_del_keymap()`. --- --- @param mode string @@ -1010,14 +1050,14 @@ function vim.api.nvim_del_var(name) end --- Echo a message. --- --- @param chunks any[] A list of [text, hl_group] arrays, each representing a text ---- chunk with specified highlight. `hl_group` element can be ---- omitted for no highlight. +--- chunk with specified highlight. `hl_group` element can be +--- omitted for no highlight. --- @param history boolean if true, add to `message-history`. --- @param opts vim.api.keyset.echo_opts Optional parameters. ---- • verbose: Message was printed as a result of 'verbose' ---- option if Nvim was invoked with -V3log_file, the message ---- will be redirected to the log_file and suppressed from ---- direct output. +--- • verbose: Message was printed as a result of 'verbose' option +--- if Nvim was invoked with -V3log_file, the message will be +--- redirected to the log_file and suppressed from direct +--- output. function vim.api.nvim_echo(chunks, history, opts) end --- Writes a message to the Vim error buffer. Does not append "\n", the @@ -1034,6 +1074,7 @@ function vim.api.nvim_err_writeln(str) end --- Evaluates a Vimscript `expression`. Dictionaries and Lists are recursively --- expanded. +--- --- On execution error: fails with Vimscript error, updates v:errmsg. --- --- @param expr string Vimscript expression string @@ -1068,8 +1109,10 @@ function vim.api.nvim_exec(src, output) end --- Executes Vimscript (multiline block of Ex commands), like anonymous --- `:source`. +--- --- Unlike `nvim_command()` this function supports heredocs, script-scope --- (s:), etc. +--- --- On execution error: fails with Vimscript error, updates v:errmsg. --- --- @param src string Vimscript code @@ -1084,24 +1127,27 @@ function vim.api.nvim_exec2(src, opts) end --- --- @param event any (String|Array) The event or events to execute --- @param opts vim.api.keyset.exec_autocmds Dictionary of autocommand options: ---- • group (string|integer) optional: the autocommand group name ---- or id to match against. `autocmd-groups`. ---- • pattern (string|array) optional: defaults to "*" ---- `autocmd-pattern`. Cannot be used with {buffer}. ---- • buffer (integer) optional: buffer number ---- `autocmd-buflocal`. Cannot be used with {pattern}. ---- • modeline (bool) optional: defaults to true. Process the ---- modeline after the autocommands ``. ---- • data (any): arbitrary data to send to the autocommand ---- callback. See `nvim_create_autocmd()` for details. +--- • group (string|integer) optional: the autocommand group name +--- or id to match against. `autocmd-groups`. +--- • pattern (string|array) optional: defaults to "*" +--- `autocmd-pattern`. Cannot be used with {buffer}. +--- • buffer (integer) optional: buffer number `autocmd-buflocal`. +--- Cannot be used with {pattern}. +--- • modeline (bool) optional: defaults to true. Process the +--- modeline after the autocommands ``. +--- • data (any): arbitrary data to send to the autocommand +--- callback. See `nvim_create_autocmd()` for details. function vim.api.nvim_exec_autocmds(event, opts) end --- Sends input-keys to Nvim, subject to various quirks controlled by `mode` --- flags. This is a blocking call, unlike `nvim_input()`. +--- --- On execution error: does not fail, but updates v:errmsg. +--- --- To input sequences like use `nvim_replace_termcodes()` (typically --- with escape_ks=false) to replace `keycodes`, then pass the result to --- nvim_feedkeys(). +--- --- Example: --- --- ```vim @@ -1109,6 +1155,7 @@ function vim.api.nvim_exec_autocmds(event, opts) end --- :call nvim_feedkeys(key, 'n', v:false) --- ``` --- +--- --- @param keys string to be typed --- @param mode string behavior flags, see `feedkeys()` --- @param escape_ks boolean If true, escape K_SPECIAL bytes in `keys`. This should be @@ -1117,6 +1164,7 @@ function vim.api.nvim_exec_autocmds(event, opts) end function vim.api.nvim_feedkeys(keys, mode, escape_ks) end --- Gets the option information for all options. +--- --- The dictionary has the full option names as keys and option metadata --- dictionaries as detailed at `nvim_get_option_info2()`. --- @@ -1124,6 +1172,7 @@ function vim.api.nvim_feedkeys(keys, mode, escape_ks) end function vim.api.nvim_get_all_options_info() end --- Get all autocommands that match the corresponding {opts}. +--- --- These examples will get autocommands matching ALL the given criteria: --- --- ```lua @@ -1164,6 +1213,7 @@ function vim.api.nvim_get_chan_info(chan) end --- Returns the 24-bit RGB value of a `nvim_get_color_map()` color name or --- "#rrggbb" hexadecimal string. +--- --- Example: --- --- ```vim @@ -1171,11 +1221,13 @@ function vim.api.nvim_get_chan_info(chan) end --- :echo nvim_get_color_by_name("#cbcbcb") --- ``` --- +--- --- @param name string Color name or "#rrggbb" string --- @return integer function vim.api.nvim_get_color_by_name(name) end --- Returns a map of color names and RGB values. +--- --- Keys are color names (e.g. "Aqua") and values are 24-bit RGB color values --- (e.g. 65535). --- @@ -1183,6 +1235,7 @@ function vim.api.nvim_get_color_by_name(name) end function vim.api.nvim_get_color_map() end --- Gets a map of global (non-buffer-local) Ex commands. +--- --- Currently only `user-commands` are supported, not builtin Ex commands. --- --- @param opts vim.api.keyset.get_commands Optional parameters. Currently only supports {"builtin":false} @@ -1223,12 +1276,12 @@ function vim.api.nvim_get_current_win() end --- `nvim_get_namespaces()`. Use 0 to get global highlight groups --- `:highlight`. --- @param opts vim.api.keyset.get_highlight Options dict: ---- • name: (string) Get a highlight definition by name. ---- • id: (integer) Get a highlight definition by id. ---- • link: (boolean, default true) Show linked group name ---- instead of effective definition `:hi-link`. ---- • create: (boolean, default true) When highlight group ---- doesn't exist create it. +--- • name: (string) Get a highlight definition by name. +--- • id: (integer) Get a highlight definition by id. +--- • link: (boolean, default true) Show linked group name instead +--- of effective definition `:hi-link`. +--- • create: (boolean, default true) When highlight group doesn't +--- exist create it. --- @return vim.api.keyset.hl_info function vim.api.nvim_get_hl(ns_id, opts) end @@ -1245,6 +1298,7 @@ function vim.api.nvim_get_hl_by_id(hl_id, rgb) end function vim.api.nvim_get_hl_by_name(name, rgb) end --- Gets a highlight group by name +--- --- similar to `hlID()`, but allocates a new ID if not present. --- --- @param name string @@ -1270,6 +1324,7 @@ function vim.api.nvim_get_keymap(mode) end --- Returns a `(row, col, buffer, buffername)` tuple representing the position --- of the uppercase/file named mark. "End of line" column position is --- returned as `v:maxcol` (big number). See `mark-motions`. +--- --- Marks are (1,0)-indexed. `api-indexing` --- --- @param name string Mark name @@ -1299,6 +1354,7 @@ function vim.api.nvim_get_option(name) end function vim.api.nvim_get_option_info(name) end --- Gets the option information for one option from arbitrary buffer or window +--- --- Resulting dictionary has keys: --- • name: Name of the option (like 'filetype') --- • shortname: Shortened name of the option (like 'ft') @@ -1360,10 +1416,12 @@ function vim.api.nvim_get_proc(pid) end function vim.api.nvim_get_proc_children(pid) end --- Find files in runtime directories +--- --- "name" can contain wildcards. For example --- nvim_get_runtime_file("colors/*.vim", true) will return all color scheme --- files. Always use forward slashes (/) in the search pattern for --- subdirectories regardless of platform. +--- --- It is not an error to not find any files. An empty array is returned then. --- --- @param name string pattern of files to search for @@ -1386,6 +1444,7 @@ function vim.api.nvim_get_vvar(name) end --- Queues raw user-input. Unlike `nvim_feedkeys()`, this uses a low-level --- input buffer and the call is non-blocking (input is processed --- asynchronously by the eventloop). +--- --- On execution error: does not fail, but updates v:errmsg. --- --- @param keys string to be typed @@ -1393,14 +1452,15 @@ function vim.api.nvim_get_vvar(name) end function vim.api.nvim_input(keys) end --- Send mouse event from GUI. +--- --- Non-blocking: does not wait on any result, but queues the event to be --- processed soon by the event loop. --- --- @param button string Mouse button: one of "left", "right", "middle", "wheel", ---- "move", "x1", "x2". ---- @param action string For ordinary buttons, one of "press", "drag", "release". ---- For the wheel, one of "up", "down", "left", "right". ---- Ignored for "move". +--- "move", "x1", "x2". +--- @param action string For ordinary buttons, one of "press", "drag", "release". For +--- the wheel, one of "up", "down", "left", "right". Ignored for +--- "move". --- @param modifier string String of modifiers each represented by a single char. The --- same specifiers are used as for a key press, except that --- the "-" separator is optional, so "C-A-", "c-a" and "CA" @@ -1411,6 +1471,7 @@ function vim.api.nvim_input(keys) end function vim.api.nvim_input_mouse(button, action, modifier, grid, row, col) end --- Gets the current list of buffer handles +--- --- Includes unlisted (unloaded/deleted) buffers, like `:ls!`. Use --- `nvim_buf_is_loaded()` to check if a buffer is loaded. --- @@ -1449,6 +1510,7 @@ function vim.api.nvim_list_wins() end function vim.api.nvim_load_context(dict) end --- Notify the user with a message +--- --- Relays the call to vim.notify . By default forwards your message in the --- echo area but can be overridden to trigger desktop notifications. --- @@ -1459,10 +1521,12 @@ function vim.api.nvim_load_context(dict) end function vim.api.nvim_notify(msg, log_level, opts) end --- Open a terminal instance in a buffer +--- --- By default (and currently the only option) the terminal will not be --- connected to an external process. Instead, input send on the channel will --- be echoed directly by the terminal. This is useful to display ANSI --- terminal sequences returned as part of a rpc message, or similar. +--- --- Note: to directly initiate the terminal using the right size, display the --- buffer in a configured window before calling this. For instance, for a --- floating display, first create an empty buffer using `nvim_create_buf()`, @@ -1472,27 +1536,30 @@ function vim.api.nvim_notify(msg, log_level, opts) end --- --- @param buffer integer the buffer to use (expected to be empty) --- @param opts vim.api.keyset.open_term Optional parameters. ---- • on_input: Lua callback for input sent, i e keypresses in ---- terminal mode. Note: keypresses are sent raw as they would ---- be to the pty master end. For instance, a carriage return ---- is sent as a "\r", not as a "\n". `textlock` applies. It ---- is possible to call `nvim_chan_send()` directly in the ---- callback however. ["input", term, bufnr, data] ---- • force_crlf: (boolean, default true) Convert "\n" to ---- "\r\n". +--- • on_input: Lua callback for input sent, i e keypresses in +--- terminal mode. Note: keypresses are sent raw as they would +--- be to the pty master end. For instance, a carriage return is +--- sent as a "\r", not as a "\n". `textlock` applies. It is +--- possible to call `nvim_chan_send()` directly in the callback +--- however. ["input", term, bufnr, data] +--- • force_crlf: (boolean, default true) Convert "\n" to "\r\n". --- @return integer function vim.api.nvim_open_term(buffer, opts) end --- Opens a new split window, or a floating window if `relative` is specified, --- or an external window (managed by the UI) if `external` is specified. +--- --- Floats are windows that are drawn above the split layout, at some anchor --- position in some other window. Floats can be drawn internally or by --- external GUI with the `ui-multigrid` extension. External windows are only --- supported with multigrid GUIs, and are displayed as separate top-level --- windows. +--- --- For a general overview of floats, see `api-floatwin`. +--- --- The `width` and `height` of the new window must be specified when opening --- a floating window, but are optional for normal windows. +--- --- If `relative` and `external` are omitted, a normal "split" window is --- created. The `win` property determines which window will be split. If no --- `win` is provided or `win == 0`, a window will be created adjacent to the @@ -1501,15 +1568,18 @@ function vim.api.nvim_open_term(buffer, opts) end --- control split direction. For `vertical`, the exact direction is determined --- by `'splitright'` and `'splitbelow'`. Split windows cannot have --- `bufpos`/`row`/`col`/`border`/`title`/`footer` properties. +--- --- With relative=editor (row=0,col=0) refers to the top-left corner of the --- screen-grid and (row=Lines-1,col=Columns-1) refers to the bottom-right --- corner. Fractional values are allowed, but the builtin implementation --- (used by non-multigrid UIs) will always round down to nearest integer. +--- --- Out-of-bounds values, and configurations that make the float not fit --- inside the main editor, are allowed. The builtin implementation truncates --- values so floats are fully within the main screen grid. External GUIs --- could let floats hover outside of the main window like a tooltip, but this --- should not be used to specify arbitrary WM screen positions. +--- --- Example (Lua): window-relative float --- --- ```lua @@ -1533,6 +1603,7 @@ function vim.api.nvim_open_term(buffer, opts) end --- }) --- ``` --- +--- --- @param buffer integer Buffer to display, or 0 for current buffer --- @param enter boolean Enter the window (make it the current window) --- @param config vim.api.keyset.win_config Map defining the window configuration. Keys: @@ -1543,7 +1614,6 @@ function vim.api.nvim_open_term(buffer, opts) end --- window. --- • "cursor" Cursor position in current window. --- • "mouse" Mouse position ---- --- • win: `window-ID` window to split, or relative window when --- creating a float (relative="win"). --- • anchor: Decides which corner of the float to place at @@ -1552,17 +1622,15 @@ function vim.api.nvim_open_term(buffer, opts) end --- • "NE" northeast --- • "SW" southwest --- • "SE" southeast ---- --- • width: Window width (in character cells). Minimum of 1. --- • height: Window height (in character cells). Minimum of 1. --- • bufpos: Places float relative to buffer text (only when --- relative="win"). Takes a tuple of zero-indexed [line, ---- column]. `row` and `col` if given are ---- applied relative to this position, else they default to: +--- column]. `row` and `col` if given are applied relative to +--- this position, else they default to: --- • `row=1` and `col=0` if `anchor` is "NW" or "NE" --- • `row=0` and `col=0` if `anchor` is "SW" or "SE" (thus --- like a tooltip near the buffer text). ---- --- • row: Row position in units of "screen cell height", may be --- fractional. --- • col: Column position in units of "screen cell width", may @@ -1583,7 +1651,6 @@ function vim.api.nvim_open_term(buffer, opts) end --- wildoptions+=pum) The default value for floats are 50. --- In general, values below 100 are recommended, unless --- there is a good reason to overshadow builtin elements. ---- --- • style: (optional) Configure the appearance of the window. --- Currently only supports one value: --- • "minimal" Nvim will display the window with many UI @@ -1596,14 +1663,13 @@ function vim.api.nvim_open_term(buffer, opts) end --- empty. The end-of-buffer region is hidden by setting --- `eob` flag of 'fillchars' to a space char, and clearing --- the `hl-EndOfBuffer` region in 'winhighlight'. ---- --- • border: Style of (optional) window border. This can either --- be a string or an array. The string values are --- • "none": No border (default). --- • "single": A single line box. --- • "double": A double line box. ---- • "rounded": Like "single", but with rounded corners ("╭" ---- etc.). +--- • "rounded": Like "single", but with rounded corners +--- ("╭" etc.). --- • "solid": Adds padding by a single whitespace cell. --- • "shadow": A drop shadow effect by blending with the --- background. @@ -1611,18 +1677,35 @@ function vim.api.nvim_open_term(buffer, opts) end --- any divisor of eight. The array will specify the eight --- chars building up the border in a clockwise fashion --- starting with the top-left corner. As an example, the ---- double box style could be specified as [ "╔", "═" ,"╗", ---- "║", "╝", "═", "╚", "║" ]. If the number of chars are ---- less than eight, they will be repeated. Thus an ASCII ---- border could be specified as [ "/", "-", "\\", "|" ], or ---- all chars the same as [ "x" ]. An empty string can be ---- used to turn off a specific border, for instance, [ "", ---- "", "", ">", "", "", "", "<" ] will only make vertical ---- borders but not horizontal ones. By default, ---- `FloatBorder` highlight is used, which links to ---- `WinSeparator` when not defined. It could also be ---- specified by character: [ ["+", "MyCorner"], ["x", ---- "MyBorder"] ]. +--- double box style could be specified as: +--- ``` +--- [ "╔", "═" ,"╗", "║", "╝", "═", "╚", "║" ]. +--- ``` +--- +--- If the number of chars are less than eight, they will be +--- repeated. Thus an ASCII border could be specified as +--- ``` +--- [ "/", "-", \"\\\\\", "|" ], +--- ``` +--- +--- or all chars the same as +--- ``` +--- [ "x" ]. +--- ``` +--- +--- An empty string can be used to turn off a specific border, +--- for instance, +--- ``` +--- [ "", "", "", ">", "", "", "", "<" ] +--- ``` +--- +--- will only make vertical borders but not horizontal ones. +--- By default, `FloatBorder` highlight is used, which links +--- to `WinSeparator` when not defined. It could also be +--- specified by character: +--- ``` +--- [ ["+", "MyCorner"], ["x", "MyBorder"] ]. +--- ``` --- --- • title: Title (optional) in window border, string or list. --- List should consist of `[text, highlight]` tuples. If @@ -1654,6 +1737,7 @@ function vim.api.nvim_open_win(buffer, enter, config) end function vim.api.nvim_out_write(str) end --- Parse command line. +--- --- Doesn't check the validity of command arguments. --- --- @param str string Command line string to parse. Cannot contain "\n". @@ -1665,17 +1749,17 @@ function vim.api.nvim_parse_cmd(str, opts) end --- --- @param expr string Expression to parse. Always treated as a single line. --- @param flags string Flags: ---- • "m" if multiple expressions in a row are allowed (only ---- the first one will be parsed), ---- • "E" if EOC tokens are not allowed (determines whether ---- they will stop parsing process or be recognized as an ---- operator/space, though also yielding an error). ---- • "l" when needing to start parsing with lvalues for ---- ":let" or ":for". Common flag sets: ---- • "m" to parse like for ":echo". ---- • "E" to parse like for "=". ---- • empty string for ":call". ---- • "lm" to parse for ":let". +--- • "m" if multiple expressions in a row are allowed (only the +--- first one will be parsed), +--- • "E" if EOC tokens are not allowed (determines whether they +--- will stop parsing process or be recognized as an +--- operator/space, though also yielding an error). +--- • "l" when needing to start parsing with lvalues for ":let" +--- or ":for". Common flag sets: +--- • "m" to parse like for ":echo". +--- • "E" to parse like for "=". +--- • empty string for ":call". +--- • "lm" to parse for ":let". --- @param highlight boolean If true, return value will also include "highlight" key --- containing array of 4-tuples (arrays) (Integer, Integer, --- Integer, String), where first three numbers define the @@ -1686,8 +1770,10 @@ function vim.api.nvim_parse_cmd(str, opts) end function vim.api.nvim_parse_expression(expr, flags, highlight) end --- Pastes at cursor, in any mode. +--- --- Invokes the `vim.paste` handler, which handles each mode appropriately. --- Sets redo/undo. Faster than `nvim_input()`. Lines break at LF ("\n"). +--- --- Errors ('nomodifiable', `vim.paste()` failure, …) are reflected in `err` --- but do not affect the return value (which is strictly decided by --- `vim.paste()`). On error, subsequent calls are ignored ("drained") until @@ -1696,8 +1782,8 @@ function vim.api.nvim_parse_expression(expr, flags, highlight) end --- @param data string Multiline input. May be binary (containing NUL bytes). --- @param crlf boolean Also break lines at CR and CRLF. --- @param phase integer -1: paste in a single call (i.e. without streaming). To ---- "stream" a paste, call `nvim_paste` sequentially ---- with these `phase` values: +--- "stream" a paste, call `nvim_paste` sequentially with these +--- `phase` values: --- • 1: starts the paste (exactly once) --- • 2: continues the paste (zero or more times) --- • 3: ends the paste (exactly once) @@ -1705,16 +1791,16 @@ function vim.api.nvim_parse_expression(expr, flags, highlight) end function vim.api.nvim_paste(data, crlf, phase) end --- Puts text at cursor, in any mode. +--- --- Compare `:put` and `p` which are always linewise. --- --- @param lines string[] `readfile()`-style list of lines. `channel-lines` --- @param type string Edit behavior: any `getregtype()` result, or: ---- • "b" `blockwise-visual` mode (may include width, e.g. "b3") ---- • "c" `charwise` mode ---- • "l" `linewise` mode ---- • "" guess by contents, see `setreg()` ---- @param after boolean If true insert after cursor (like `p`), or before (like ---- `P`). +--- • "b" `blockwise-visual` mode (may include width, e.g. "b3") +--- • "c" `charwise` mode +--- • "l" `linewise` mode +--- • "" guess by contents, see `setreg()` +--- @param after boolean If true insert after cursor (like `p`), or before (like `P`). --- @param follow boolean If true place cursor at end of inserted text. function vim.api.nvim_put(lines, type, after, follow) end @@ -1729,14 +1815,15 @@ function vim.api.nvim_put(lines, type, after, follow) end function vim.api.nvim_replace_termcodes(str, from_part, do_lt, special) end --- Selects an item in the completion popup menu. +--- --- If neither `ins-completion` nor `cmdline-completion` popup menu is active --- this API call is silently ignored. Useful for an external UI using --- `ui-popupmenu` to control the popup menu with the mouse. Can also be used --- in a mapping; use `:map-cmd` or a Lua mapping to ensure the mapping --- doesn't end completion mode. --- ---- @param item integer Index (zero-based) of the item to select. Value of -1 ---- selects nothing and restores the original text. +--- @param item integer Index (zero-based) of the item to select. Value of -1 selects +--- nothing and restores the original text. --- @param insert boolean For `ins-completion`, whether the selection should be --- inserted in the buffer. Ignored for `cmdline-completion`. --- @param finish boolean Finish the completion and dismiss the popup menu. Implies @@ -1770,13 +1857,16 @@ function vim.api.nvim_set_current_tabpage(tabpage) end function vim.api.nvim_set_current_win(window) end --- Set or change decoration provider for a `namespace` +--- --- This is a very general purpose interface for having Lua callbacks being --- triggered during the redraw code. +--- --- The expected usage is to set `extmarks` for the currently redrawn buffer. --- `nvim_buf_set_extmark()` can be called to add marks on a per-window or --- per-lines basis. Use the `ephemeral` key to only use the mark for the --- current screen redraw (the callback will be called again for the next --- redraw). +--- --- Note: this function should not be called often. Rather, the callbacks --- themselves can be used to throttle unneeded callbacks. the `on_start` --- callback can return `false` to disable the provider until the next redraw. @@ -1785,26 +1875,27 @@ function vim.api.nvim_set_current_win(window) end --- plugin managing multiple sources of decoration should ideally only set one --- provider, and merge the sources internally. You can use multiple `ns_id` --- for the extmarks set/modified inside the callback anyway. +--- --- Note: doing anything other than setting extmarks is considered --- experimental. Doing things like changing options are not explicitly --- forbidden, but is likely to have unexpected consequences (such as 100% CPU --- consumption). doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is --- quite dubious for the moment. +--- --- Note: It is not allowed to remove or update extmarks in 'on_line' --- callbacks. --- --- @param ns_id integer Namespace id from `nvim_create_namespace()` --- @param opts vim.api.keyset.set_decoration_provider Table of callbacks: ---- • on_start: called first on each screen redraw ["start", ---- tick] ---- • on_buf: called for each buffer being redrawn (before window ---- callbacks) ["buf", bufnr, tick] ---- • on_win: called when starting to redraw a specific window. ---- ["win", winid, bufnr, topline, botline] ---- • on_line: called for each buffer line being redrawn. (The ---- interaction with fold lines is subject to change) ["line", ---- winid, bufnr, row] ---- • on_end: called at the end of a redraw cycle ["end", tick] +--- • on_start: called first on each screen redraw ["start", tick] +--- • on_buf: called for each buffer being redrawn (before window +--- callbacks) ["buf", bufnr, tick] +--- • on_win: called when starting to redraw a specific window. +--- ["win", winid, bufnr, topline, botline] +--- • on_line: called for each buffer line being redrawn. (The +--- interaction with fold lines is subject to change) ["line", +--- winid, bufnr, row] +--- • on_end: called at the end of a redraw cycle ["end", tick] function vim.api.nvim_set_decoration_provider(ns_id, opts) end --- Sets a highlight group. @@ -1816,31 +1907,31 @@ function vim.api.nvim_set_decoration_provider(ns_id, opts) end --- activate them. --- @param name string Highlight group name, e.g. "ErrorMsg" --- @param val vim.api.keyset.highlight Highlight definition map, accepts the following keys: ---- • fg: color name or "#RRGGBB", see note. ---- • bg: color name or "#RRGGBB", see note. ---- • sp: color name or "#RRGGBB" ---- • blend: integer between 0 and 100 ---- • bold: boolean ---- • standout: boolean ---- • underline: boolean ---- • undercurl: boolean ---- • underdouble: boolean ---- • underdotted: boolean ---- • underdashed: boolean ---- • strikethrough: boolean ---- • italic: boolean ---- • reverse: boolean ---- • nocombine: boolean ---- • link: name of another highlight group to link to, see ---- `:hi-link`. ---- • default: Don't override existing definition `:hi-default` ---- • ctermfg: Sets foreground of cterm color `ctermfg` ---- • ctermbg: Sets background of cterm color `ctermbg` ---- • cterm: cterm attribute map, like `highlight-args`. If not ---- set, cterm attributes will match those from the attribute ---- map documented above. ---- • force: if true force update the highlight group when it ---- exists. +--- • fg: color name or "#RRGGBB", see note. +--- • bg: color name or "#RRGGBB", see note. +--- • sp: color name or "#RRGGBB" +--- • blend: integer between 0 and 100 +--- • bold: boolean +--- • standout: boolean +--- • underline: boolean +--- • undercurl: boolean +--- • underdouble: boolean +--- • underdotted: boolean +--- • underdashed: boolean +--- • strikethrough: boolean +--- • italic: boolean +--- • reverse: boolean +--- • nocombine: boolean +--- • link: name of another highlight group to link to, see +--- `:hi-link`. +--- • default: Don't override existing definition `:hi-default` +--- • ctermfg: Sets foreground of cterm color `ctermfg` +--- • ctermbg: Sets background of cterm color `ctermbg` +--- • cterm: cterm attribute map, like `highlight-args`. If not +--- set, cterm attributes will match those from the attribute map +--- documented above. +--- • force: if true force update the highlight group when it +--- exists. function vim.api.nvim_set_hl(ns_id, name, val) end --- Set active namespace for highlights defined with `nvim_set_hl()`. This can @@ -1851,6 +1942,7 @@ function vim.api.nvim_set_hl_ns(ns_id) end --- Set active namespace for highlights defined with `nvim_set_hl()` while --- redrawing. +--- --- This function meant to be called while redrawing, primarily from --- `nvim_set_decoration_provider()` on_win and on_line callbacks, which are --- allowed to change the namespace during a redraw cycle. @@ -1859,9 +1951,12 @@ function vim.api.nvim_set_hl_ns(ns_id) end function vim.api.nvim_set_hl_ns_fast(ns_id) end --- Sets a global `mapping` for the given mode. +--- --- To set a buffer-local mapping, use `nvim_buf_set_keymap()`. +--- --- Unlike `:map`, leading/trailing whitespace is accepted as part of the --- {lhs} or {rhs}. Empty {rhs} is ``. `keycodes` are replaced as usual. +--- --- Example: --- --- ```vim @@ -1874,8 +1969,9 @@ function vim.api.nvim_set_hl_ns_fast(ns_id) end --- nmap --- ``` --- ---- @param mode string Mode short-name (map command prefix: "n", "i", "v", "x", …) or ---- "!" for `:map!`, or empty string for `:map`. "ia", "ca" or +--- +--- @param mode string Mode short-name (map command prefix: "n", "i", "v", "x", …) +--- or "!" for `:map!`, or empty string for `:map`. "ia", "ca" or --- "!a" for abbreviation in Insert mode, Cmdline mode, or both, --- respectively --- @param lhs string Left-hand-side `{lhs}` of the mapping. @@ -1899,15 +1995,16 @@ function vim.api.nvim_set_option(name, value) end --- Sets the value of an option. The behavior of this function matches that of --- `:set`: for global-local options, both the global and local value are set --- unless otherwise specified with {scope}. +--- --- Note the options {win} and {buf} cannot be used together. --- --- @param name string Option name --- @param value any New option value --- @param opts vim.api.keyset.option Optional parameters ---- • scope: One of "global" or "local". Analogous to ---- `:setglobal` and `:setlocal`, respectively. ---- • win: `window-ID`. Used for setting window local option. ---- • buf: Buffer number. Used for setting buffer local option. +--- • scope: One of "global" or "local". Analogous to `:setglobal` +--- and `:setlocal`, respectively. +--- • win: `window-ID`. Used for setting window local option. +--- • buf: Buffer number. Used for setting buffer local option. function vim.api.nvim_set_option_value(name, value, opts) end --- Sets a global (g:) variable. @@ -1990,7 +2087,7 @@ function vim.api.nvim_win_add_ns(window, ns_id) end --- --- @param window integer Window handle, or 0 for current window --- @param fun function Function to call inside the window (currently Lua callable ---- only) +--- only) --- @return any function vim.api.nvim_win_call(window, fun) end @@ -1998,8 +2095,8 @@ function vim.api.nvim_win_call(window, fun) end --- --- @param window integer Window handle, or 0 for current window --- @param force boolean Behave like `:close!` The last window of a buffer with ---- unwritten changes can be closed. The buffer will become ---- hidden, even if 'hidden' is not set. +--- unwritten changes can be closed. The buffer will become +--- hidden, even if 'hidden' is not set. function vim.api.nvim_win_close(window, force) end --- Removes a window-scoped (w:) variable @@ -2015,7 +2112,9 @@ function vim.api.nvim_win_del_var(window, name) end function vim.api.nvim_win_get_buf(window) end --- Gets window configuration. +--- --- The returned value may be given to `nvim_open_win()`. +--- --- `relative` is empty for normal windows. --- --- @param window integer Window handle, or 0 for current window @@ -2081,6 +2180,7 @@ function vim.api.nvim_win_get_width(window) end --- Closes the window and hide the buffer it contains (like `:hide` with a --- `window-ID`). +--- --- Like `:hide` the buffer becomes hidden unless another window is editing --- it, or 'bufhidden' is `unload`, `delete` or `wipe` as opposed to `:close` --- or `nvim_win_close()`, which will close the buffer. @@ -2109,6 +2209,7 @@ function vim.api.nvim_win_set_buf(window, buffer) end --- Configures window layout. Currently only for floating and external windows --- (including changing a split window to those layouts). +--- --- When reconfiguring a floating window, absent option keys will not be --- changed. `row`/`col` and `relative` must be reconfigured together. --- @@ -2132,6 +2233,7 @@ function vim.api.nvim_win_set_height(window, height) end --- Set highlight namespace for a window. This will use highlights defined --- with `nvim_set_hl()` for this namespace, but fall back to global --- highlights (ns=0) when missing. +--- --- This takes precedence over the 'winhighlight' option. --- --- @param window integer @@ -2160,23 +2262,26 @@ function vim.api.nvim_win_set_width(window, width) end --- Computes the number of screen lines occupied by a range of text in a given --- window. Works for off-screen text and takes folds into account. +--- --- Diff filler or virtual lines above a line are counted as a part of that --- line, unless the line is on "start_row" and "start_vcol" is specified. +--- --- Diff filler or virtual lines below the last buffer line are counted in the --- result when "end_row" is omitted. +--- --- Line indexing is similar to `nvim_buf_get_text()`. --- --- @param window integer Window handle, or 0 for current window. --- @param opts vim.api.keyset.win_text_height Optional parameters: ---- • start_row: Starting line index, 0-based inclusive. When ---- omitted start at the very top. ---- • end_row: Ending line index, 0-based inclusive. When ---- omitted end at the very bottom. ---- • start_vcol: Starting virtual column index on "start_row", ---- 0-based inclusive, rounded down to full screen lines. When ---- omitted include the whole line. ---- • end_vcol: Ending virtual column index on "end_row", ---- 0-based exclusive, rounded up to full screen lines. When ---- omitted include the whole line. +--- • start_row: Starting line index, 0-based inclusive. When +--- omitted start at the very top. +--- • end_row: Ending line index, 0-based inclusive. When omitted +--- end at the very bottom. +--- • start_vcol: Starting virtual column index on "start_row", +--- 0-based inclusive, rounded down to full screen lines. When +--- omitted include the whole line. +--- • end_vcol: Ending virtual column index on "end_row", 0-based +--- exclusive, rounded up to full screen lines. When omitted +--- include the whole line. --- @return table function vim.api.nvim_win_text_height(window, opts) end diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua index a422a65792..472162ecc1 100644 --- a/runtime/lua/vim/_meta/builtin.lua +++ b/runtime/lua/vim/_meta/builtin.lua @@ -3,65 +3,63 @@ error('Cannot require a meta file') ----@defgroup vim.builtin ---- ----@brief
help
----vim.api.{func}({...})                                                    *vim.api*
----    Invokes Nvim |API| function {func} with arguments {...}.
----    Example: call the "nvim_get_current_line()" API function: >lua
----        print(tostring(vim.api.nvim_get_current_line()))
----
----vim.NIL                                                                  *vim.NIL*
----    Special value representing NIL in |RPC| and |v:null| in Vimscript
----    conversion, and similar cases. Lua `nil` cannot be used as part of a Lua
----    table representing a Dictionary or Array, because it is treated as
----    missing: `{"foo", nil}` is the same as `{"foo"}`.
----
----vim.type_idx                                                        *vim.type_idx*
----    Type index for use in |lua-special-tbl|. Specifying one of the values from
----    |vim.types| allows typing the empty table (it is unclear whether empty Lua
----    table represents empty list or empty array) and forcing integral numbers
----    to be |Float|. See |lua-special-tbl| for more details.
----
----vim.val_idx                                                          *vim.val_idx*
----    Value index for tables representing |Float|s. A table representing
----    floating-point value 1.0 looks like this: >lua
----        {
----          [vim.type_idx] = vim.types.float,
----          [vim.val_idx] = 1.0,
----        }
----<    See also |vim.type_idx| and |lua-special-tbl|.
----
----vim.types                                                              *vim.types*
----    Table with possible values for |vim.type_idx|. Contains two sets of
----    key-value pairs: first maps possible values for |vim.type_idx| to
----    human-readable strings, second maps human-readable type names to values
----    for |vim.type_idx|. Currently contains pairs for `float`, `array` and
----        `dictionary` types.
----
----    Note: One must expect that values corresponding to `vim.types.float`,
----    `vim.types.array` and `vim.types.dictionary` fall under only two following
----    assumptions:
----    1. Value may serve both as a key and as a value in a table. Given the
----       properties of Lua tables this basically means “value is not `nil`”.
----    2. For each value in `vim.types` table `vim.types[vim.types[value]]` is the
----       same as `value`.
----    No other restrictions are put on types, and it is not guaranteed that
----    values corresponding to `vim.types.float`, `vim.types.array` and
----    `vim.types.dictionary` will not change or that `vim.types` table will only
----    contain values for these three types.
----
----                                                   *log_levels* *vim.log.levels*
----Log levels are one of the values defined in `vim.log.levels`:
----
----    vim.log.levels.DEBUG
----    vim.log.levels.ERROR
----    vim.log.levels.INFO
----    vim.log.levels.TRACE
----    vim.log.levels.WARN
----    vim.log.levels.OFF
----
----
+--- @brief
help
+--- vim.api.{func}({...})                                                    *vim.api*
+---     Invokes Nvim |API| function {func} with arguments {...}.
+---     Example: call the "nvim_get_current_line()" API function: >lua
+---         print(tostring(vim.api.nvim_get_current_line()))
+---
+--- vim.NIL                                                                  *vim.NIL*
+---     Special value representing NIL in |RPC| and |v:null| in Vimscript
+---     conversion, and similar cases. Lua `nil` cannot be used as part of a Lua
+---     table representing a Dictionary or Array, because it is treated as
+---     missing: `{"foo", nil}` is the same as `{"foo"}`.
+---
+--- vim.type_idx                                                        *vim.type_idx*
+---     Type index for use in |lua-special-tbl|. Specifying one of the values from
+---     |vim.types| allows typing the empty table (it is unclear whether empty Lua
+---     table represents empty list or empty array) and forcing integral numbers
+---     to be |Float|. See |lua-special-tbl| for more details.
+---
+--- vim.val_idx                                                          *vim.val_idx*
+---     Value index for tables representing |Float|s. A table representing
+---     floating-point value 1.0 looks like this: >lua
+---         {
+---           [vim.type_idx] = vim.types.float,
+---           [vim.val_idx] = 1.0,
+---         }
+--- <    See also |vim.type_idx| and |lua-special-tbl|.
+---
+--- vim.types                                                              *vim.types*
+---     Table with possible values for |vim.type_idx|. Contains two sets of
+---     key-value pairs: first maps possible values for |vim.type_idx| to
+---     human-readable strings, second maps human-readable type names to values
+---     for |vim.type_idx|. Currently contains pairs for `float`, `array` and
+---         `dictionary` types.
+---
+---     Note: One must expect that values corresponding to `vim.types.float`,
+---     `vim.types.array` and `vim.types.dictionary` fall under only two following
+---     assumptions:
+---     1. Value may serve both as a key and as a value in a table. Given the
+---        properties of Lua tables this basically means “value is not `nil`”.
+---     2. For each value in `vim.types` table `vim.types[vim.types[value]]` is the
+---        same as `value`.
+---     No other restrictions are put on types, and it is not guaranteed that
+---     values corresponding to `vim.types.float`, `vim.types.array` and
+---     `vim.types.dictionary` will not change or that `vim.types` table will only
+---     contain values for these three types.
+---
+---                                                    *log_levels* *vim.log.levels*
+--- Log levels are one of the values defined in `vim.log.levels`:
+---
+---     vim.log.levels.DEBUG
+---     vim.log.levels.ERROR
+---     vim.log.levels.INFO
+---     vim.log.levels.TRACE
+---     vim.log.levels.WARN
+---     vim.log.levels.OFF
+---
+--- 
---@class vim.NIL diff --git a/runtime/lua/vim/_meta/json.lua b/runtime/lua/vim/_meta/json.lua index e010086615..07d89aafc8 100644 --- a/runtime/lua/vim/_meta/json.lua +++ b/runtime/lua/vim/_meta/json.lua @@ -5,7 +5,7 @@ vim.json = {} -- luacheck: no unused args ----@defgroup vim.json +---@brief --- --- This module provides encoding and decoding of Lua objects to and --- from JSON-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|. diff --git a/runtime/lua/vim/_meta/lpeg.lua b/runtime/lua/vim/_meta/lpeg.lua index 5bd502a7c8..f2239e5e5a 100644 --- a/runtime/lua/vim/_meta/lpeg.lua +++ b/runtime/lua/vim/_meta/lpeg.lua @@ -5,22 +5,20 @@ error('Cannot require a meta file') -- (based on revision 4aded588f9531d89555566bb1de27490354b91c7) -- with types being renamed to include the vim namespace and with some descriptions made less verbose. ----@defgroup vim.lpeg ----
help
----LPeg is a pattern-matching library for Lua, based on
----Parsing Expression Grammars (https://bford.info/packrat/) (PEGs).
+--- @brief 
help
+--- LPeg is a pattern-matching library for Lua, based on
+--- Parsing Expression Grammars (https://bford.info/packrat/) (PEGs).
 ---
----                                                                    *lua-lpeg*
----                                                            *vim.lpeg.Pattern*
----The LPeg library for parsing expression grammars is included as `vim.lpeg`
----(https://www.inf.puc-rio.br/~roberto/lpeg/).
+---                                                                     *lua-lpeg*
+---                                                             *vim.lpeg.Pattern*
+--- The LPeg library for parsing expression grammars is included as `vim.lpeg`
+--- (https://www.inf.puc-rio.br/~roberto/lpeg/).
 ---
----In addition, its regex-like interface is available as |vim.re|
----(https://www.inf.puc-rio.br/~roberto/lpeg/re.html).
+--- In addition, its regex-like interface is available as |vim.re|
+--- (https://www.inf.puc-rio.br/~roberto/lpeg/re.html).
 ---
----
+---
---- *LPeg* is a new pattern-matching library for Lua, based on [Parsing Expression Grammars](https://bford.info/packrat/) (PEGs). vim.lpeg = {} --- @class vim.lpeg.Pattern @@ -88,6 +86,7 @@ function Pattern:match(subject, init) end --- Returns the string `"pattern"` if the given value is a pattern, otherwise `nil`. --- +--- @param value vim.lpeg.Pattern|string|integer|boolean|table|function --- @return "pattern"|nil function vim.lpeg.type(value) end diff --git a/runtime/lua/vim/_meta/mpack.lua b/runtime/lua/vim/_meta/mpack.lua index 54e097ad97..3970341b78 100644 --- a/runtime/lua/vim/_meta/mpack.lua +++ b/runtime/lua/vim/_meta/mpack.lua @@ -2,14 +2,17 @@ -- luacheck: no unused args ---- @defgroup vim.mpack +--- @brief --- --- This module provides encoding and decoding of Lua objects to and --- from msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|. --- Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object. --- @param str string +--- @return any function vim.mpack.decode(str) end --- Encodes (or "packs") Lua object {obj} as msgpack in a Lua string. +--- @param obj any +--- @return string function vim.mpack.encode(obj) end diff --git a/runtime/lua/vim/_meta/re.lua b/runtime/lua/vim/_meta/re.lua index 4f254b19a0..14c94c7824 100644 --- a/runtime/lua/vim/_meta/re.lua +++ b/runtime/lua/vim/_meta/re.lua @@ -7,15 +7,12 @@ error('Cannot require a meta file') -- Copyright © 2007-2023 Lua.org, PUC-Rio. -- See 'lpeg.html' for license ---- @defgroup vim.re ----
help
----The `vim.re` module provides a conventional regex-like syntax for pattern usage
----within LPeg |vim.lpeg|.
+--- @brief
+--- The `vim.re` module provides a conventional regex-like syntax for pattern usage
+--- within LPeg |vim.lpeg|.
 ---
----See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original
----documentation including regex syntax and more concrete examples.
----
----
+--- See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original +--- documentation including regex syntax and more concrete examples. --- Compiles the given {string} and returns an equivalent LPeg pattern. The given string may define --- either an expression or a grammar. The optional {defs} table provides extra Lua values to be used diff --git a/runtime/lua/vim/_meta/regex.lua b/runtime/lua/vim/_meta/regex.lua index 58aa2be8c2..ab403b97e7 100644 --- a/runtime/lua/vim/_meta/regex.lua +++ b/runtime/lua/vim/_meta/regex.lua @@ -2,8 +2,6 @@ -- luacheck: no unused args ---- @defgroup vim.regex ---- --- @brief Vim regexes can be used directly from Lua. Currently they only allow --- matching within a single line. diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua index b83a8dd4b1..f1fed50c6d 100644 --- a/runtime/lua/vim/_options.lua +++ b/runtime/lua/vim/_options.lua @@ -1,12 +1,10 @@ ----@defgroup lua-vimscript +--- @brief Nvim Lua provides an interface or "bridge" to Vimscript variables and +--- functions, and editor commands and options. --- ----@brief Nvim Lua provides an interface or "bridge" to Vimscript variables and ----functions, and editor commands and options. ---- ----Objects passed over this bridge are COPIED (marshalled): there are no ----"references". |lua-guide-variables| For example, using \`vim.fn.remove()\` on ----a Lua list copies the list object to Vimscript and does NOT modify the Lua ----list: +--- Objects passed over this bridge are COPIED (marshalled): there are no +--- "references". |lua-guide-variables| For example, using `vim.fn.remove()` on +--- a Lua list copies the list object to Vimscript and does NOT modify the Lua +--- list: --- --- ```lua --- local list = { 1, 2, 3 } @@ -14,86 +12,85 @@ --- vim.print(list) --> "{ 1, 2, 3 }" --- ``` ----@addtogroup lua-vimscript ----@brief
help
----vim.call({func}, {...})                                           *vim.call()*
----    Invokes |vim-function| or |user-function| {func} with arguments {...}.
----    See also |vim.fn|.
----    Equivalent to: >lua
----        vim.fn[func]({...})
----<
----vim.cmd({command})
----    See |vim.cmd()|.
----
----vim.fn.{func}({...})                                                  *vim.fn*
----    Invokes |vim-function| or |user-function| {func} with arguments {...}.
----    To call autoload functions, use the syntax: >lua
----        vim.fn['some\#function']({...})
----<
----    Unlike vim.api.|nvim_call_function()| this converts directly between Vim
----    objects and Lua objects. If the Vim function returns a float, it will be
----    represented directly as a Lua number. Empty lists and dictionaries both
----    are represented by an empty table.
----
----    Note: |v:null| values as part of the return value is represented as
----    |vim.NIL| special value
----
----    Note: vim.fn keys are generated lazily, thus `pairs(vim.fn)` only
----    enumerates functions that were called at least once.
----
----    Note: The majority of functions cannot run in |api-fast| callbacks with some
----    undocumented exceptions which are allowed.
----
----                                                           *lua-vim-variables*
----The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed
----from Lua conveniently and idiomatically by referencing the `vim.*` Lua tables
----described below. In this way you can easily read and modify global Vimscript
----variables from Lua.
----
----Example: >lua
----
----    vim.g.foo = 5     -- Set the g:foo Vimscript variable.
----    print(vim.g.foo)  -- Get and print the g:foo Vimscript variable.
----    vim.g.foo = nil   -- Delete (:unlet) the Vimscript variable.
----    vim.b[2].foo = 6  -- Set b:foo for buffer 2
----<
----
----Note that setting dictionary fields directly will not write them back into
----Nvim. This is because the index into the namespace simply returns a copy.
----Instead the whole dictionary must be written as one. This can be achieved by
----creating a short-lived temporary.
----
----Example: >lua
----
----    vim.g.my_dict.field1 = 'value'  -- Does not work
----
----    local my_dict = vim.g.my_dict   --
----    my_dict.field1 = 'value'        -- Instead do
----    vim.g.my_dict = my_dict         --
----
----vim.g                                                                  *vim.g*
----    Global (|g:|) editor variables.
----    Key with no value returns `nil`.
----
----vim.b                                                                  *vim.b*
----    Buffer-scoped (|b:|) variables for the current buffer.
----    Invalid or unset key returns `nil`. Can be indexed with
----    an integer to access variables for a specific buffer.
----
----vim.w                                                                  *vim.w*
----    Window-scoped (|w:|) variables for the current window.
----    Invalid or unset key returns `nil`. Can be indexed with
----    an integer to access variables for a specific window.
----
----vim.t                                                                  *vim.t*
----    Tabpage-scoped (|t:|) variables for the current tabpage.
----    Invalid or unset key returns `nil`. Can be indexed with
----    an integer to access variables for a specific tabpage.
----
----vim.v                                                                  *vim.v*
----    |v:| variables.
----    Invalid or unset key returns `nil`.
----
+--- @brief
help
+--- vim.call({func}, {...})                                           *vim.call()*
+---     Invokes |vim-function| or |user-function| {func} with arguments {...}.
+---     See also |vim.fn|.
+---     Equivalent to: >lua
+---         vim.fn[func]({...})
+--- <
+--- vim.cmd({command})
+---     See |vim.cmd()|.
+---
+--- vim.fn.{func}({...})                                                  *vim.fn*
+---     Invokes |vim-function| or |user-function| {func} with arguments {...}.
+---     To call autoload functions, use the syntax: >lua
+---         vim.fn['some#function']({...})
+--- <
+---     Unlike vim.api.|nvim_call_function()| this converts directly between Vim
+---     objects and Lua objects. If the Vim function returns a float, it will be
+---     represented directly as a Lua number. Empty lists and dictionaries both
+---     are represented by an empty table.
+---
+---     Note: |v:null| values as part of the return value is represented as
+---     |vim.NIL| special value
+---
+---     Note: vim.fn keys are generated lazily, thus `pairs(vim.fn)` only
+---     enumerates functions that were called at least once.
+---
+---     Note: The majority of functions cannot run in |api-fast| callbacks with some
+---     undocumented exceptions which are allowed.
+---
+---                                                            *lua-vim-variables*
+--- The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed
+--- from Lua conveniently and idiomatically by referencing the `vim.*` Lua tables
+--- described below. In this way you can easily read and modify global Vimscript
+--- variables from Lua.
+---
+--- Example: >lua
+---
+---     vim.g.foo = 5     -- Set the g:foo Vimscript variable.
+---     print(vim.g.foo)  -- Get and print the g:foo Vimscript variable.
+---     vim.g.foo = nil   -- Delete (:unlet) the Vimscript variable.
+---     vim.b[2].foo = 6  -- Set b:foo for buffer 2
+--- <
+---
+--- Note that setting dictionary fields directly will not write them back into
+--- Nvim. This is because the index into the namespace simply returns a copy.
+--- Instead the whole dictionary must be written as one. This can be achieved by
+--- creating a short-lived temporary.
+---
+--- Example: >lua
+---
+---     vim.g.my_dict.field1 = 'value'  -- Does not work
+---
+---     local my_dict = vim.g.my_dict   --
+---     my_dict.field1 = 'value'        -- Instead do
+---     vim.g.my_dict = my_dict         --
+---
+--- vim.g                                                                  *vim.g*
+---     Global (|g:|) editor variables.
+---     Key with no value returns `nil`.
+---
+--- vim.b                                                                  *vim.b*
+---     Buffer-scoped (|b:|) variables for the current buffer.
+---     Invalid or unset key returns `nil`. Can be indexed with
+---     an integer to access variables for a specific buffer.
+---
+--- vim.w                                                                  *vim.w*
+---     Window-scoped (|w:|) variables for the current window.
+---     Invalid or unset key returns `nil`. Can be indexed with
+---     an integer to access variables for a specific window.
+---
+--- vim.t                                                                  *vim.t*
+---     Tabpage-scoped (|t:|) variables for the current tabpage.
+---     Invalid or unset key returns `nil`. Can be indexed with
+---     an integer to access variables for a specific tabpage.
+---
+--- vim.v                                                                  *vim.v*
+---     |v:| variables.
+---     Invalid or unset key returns `nil`.
+--- 
local api = vim.api @@ -142,7 +139,6 @@ end --- vim.env.FOO = 'bar' --- print(vim.env.TERM) --- ``` ---- ---@param var string vim.env = setmetatable({}, { __index = function(_, k) @@ -205,31 +201,30 @@ local function new_win_opt_accessor(winid, bufnr) }) end ----@addtogroup lua-vimscript ----@brief
help
----` `                                                                *lua-options*
----                                                             *lua-vim-options*
----                                                                 *lua-vim-set*
----                                                            *lua-vim-setlocal*
+--- @brief 
help
+---                                                                  *lua-options*
+---                                                              *lua-vim-options*
+---                                                                  *lua-vim-set*
+---                                                             *lua-vim-setlocal*
 ---
----Vim options can be accessed through |vim.o|, which behaves like Vimscript
----|:set|.
+--- Vim options can be accessed through |vim.o|, which behaves like Vimscript
+--- |:set|.
 ---
----    Examples: ~
+---     Examples: ~
 ---
----    To set a boolean toggle:
----        Vimscript: `set number`
----        Lua:       `vim.o.number = true`
+---     To set a boolean toggle:
+---         Vimscript: `set number`
+---         Lua:       `vim.o.number = true`
 ---
----    To set a string value:
----        Vimscript: `set wildignore=*.o,*.a,__pycache__`
----        Lua:       `vim.o.wildignore = '*.o,*.a,__pycache__'`
+---     To set a string value:
+---         Vimscript: `set wildignore=*.o,*.a,__pycache__`
+---         Lua:       `vim.o.wildignore = '*.o,*.a,__pycache__'`
 ---
----Similarly, there is |vim.bo| and |vim.wo| for setting buffer-scoped and
----window-scoped options. Note that this must NOT be confused with
----|local-options| and |:setlocal|. There is also |vim.go| that only accesses the
----global value of a |global-local| option, see |:setglobal|.
----
+--- Similarly, there is |vim.bo| and |vim.wo| for setting buffer-scoped and +--- window-scoped options. Note that this must NOT be confused with +--- |local-options| and |:setlocal|. There is also |vim.go| that only accesses the +--- global value of a |global-local| option, see |:setglobal|. +---
--- Get or set |options|. Like `:set`. Invalid key is an error. --- @@ -310,13 +305,10 @@ vim.bo = new_buf_opt_accessor() --- ``` vim.wo = new_win_opt_accessor() ----@brief [[ --- vim.opt, vim.opt_local and vim.opt_global implementation --- --- To be used as helpers for working with options within neovim. --- For information on how to use, see :help vim.opt ---- ----@brief ]] --- Preserves the order and does not mutate the original list local function remove_duplicate_values(t) @@ -739,74 +731,73 @@ local function create_option_accessor(scope) }) end ----@addtogroup lua-vimscript ----@brief
help
----` `                                                                       *vim.opt_local*
----                                                                       *vim.opt_global*
----                                                                              *vim.opt*
----
----
----A special interface |vim.opt| exists for conveniently interacting with list-
----and map-style option from Lua: It allows accessing them as Lua tables and
----offers object-oriented method for adding and removing entries.
----
----    Examples: ~
----
----    The following methods of setting a list-style option are equivalent:
----        In Vimscript: >vim
----            set wildignore=*.o,*.a,__pycache__
----<
----        In Lua using `vim.o`: >lua
----            vim.o.wildignore = '*.o,*.a,__pycache__'
----<
----        In Lua using `vim.opt`: >lua
----            vim.opt.wildignore = { '*.o', '*.a', '__pycache__' }
----<
----    To replicate the behavior of |:set+=|, use: >lua
----
----        vim.opt.wildignore:append { "*.pyc", "node_modules" }
----<
----    To replicate the behavior of |:set^=|, use: >lua
----
----        vim.opt.wildignore:prepend { "new_first_value" }
----<
----    To replicate the behavior of |:set-=|, use: >lua
----
----        vim.opt.wildignore:remove { "node_modules" }
----<
----    The following methods of setting a map-style option are equivalent:
----        In Vimscript: >vim
----            set listchars=space:_,tab:>~
----<
----        In Lua using `vim.o`: >lua
----            vim.o.listchars = 'space:_,tab:>~'
----<
----        In Lua using `vim.opt`: >lua
----            vim.opt.listchars = { space = '_', tab = '>~' }
----<
----
----Note that |vim.opt| returns an `Option` object, not the value of the option,
----which is accessed through |vim.opt:get()|:
----
----    Examples: ~
----
----    The following methods of getting a list-style option are equivalent:
----        In Vimscript: >vim
----            echo wildignore
----<
----        In Lua using `vim.o`: >lua
----            print(vim.o.wildignore)
----<
----        In Lua using `vim.opt`: >lua
----            vim.print(vim.opt.wildignore:get())
----<
----
----In any of the above examples, to replicate the behavior |:setlocal|, use
----`vim.opt_local`. Additionally, to replicate the behavior of |:setglobal|, use
----`vim.opt_global`.
----
- ---- @diagnostic disable-next-line:unused-local used for gen_vimdoc +--- @brief
help
+---                                                                           *vim.opt_local*
+---                                                                        *vim.opt_global*
+---                                                                               *vim.opt*
+---
+---
+--- A special interface |vim.opt| exists for conveniently interacting with list-
+--- and map-style option from Lua: It allows accessing them as Lua tables and
+--- offers object-oriented method for adding and removing entries.
+---
+---     Examples: ~
+---
+---     The following methods of setting a list-style option are equivalent:
+---         In Vimscript: >vim
+---             set wildignore=*.o,*.a,__pycache__
+--- <
+---         In Lua using `vim.o`: >lua
+---             vim.o.wildignore = '*.o,*.a,__pycache__'
+--- <
+---         In Lua using `vim.opt`: >lua
+---             vim.opt.wildignore = { '*.o', '*.a', '__pycache__' }
+--- <
+---     To replicate the behavior of |:set+=|, use: >lua
+---
+---         vim.opt.wildignore:append { "*.pyc", "node_modules" }
+--- <
+---     To replicate the behavior of |:set^=|, use: >lua
+---
+---         vim.opt.wildignore:prepend { "new_first_value" }
+--- <
+---     To replicate the behavior of |:set-=|, use: >lua
+---
+---         vim.opt.wildignore:remove { "node_modules" }
+--- <
+---     The following methods of setting a map-style option are equivalent:
+---         In Vimscript: >vim
+---             set listchars=space:_,tab:>~
+--- <
+---         In Lua using `vim.o`: >lua
+---             vim.o.listchars = 'space:_,tab:>~'
+--- <
+---         In Lua using `vim.opt`: >lua
+---             vim.opt.listchars = { space = '_', tab = '>~' }
+--- <
+---
+--- Note that |vim.opt| returns an `Option` object, not the value of the option,
+--- which is accessed through |vim.opt:get()|:
+---
+---     Examples: ~
+---
+---     The following methods of getting a list-style option are equivalent:
+---         In Vimscript: >vim
+---             echo wildignore
+--- <
+---         In Lua using `vim.o`: >lua
+---             print(vim.o.wildignore)
+--- <
+---         In Lua using `vim.opt`: >lua
+---             vim.print(vim.opt.wildignore:get())
+--- <
+---
+--- In any of the above examples, to replicate the behavior |:setlocal|, use
+--- `vim.opt_local`. Additionally, to replicate the behavior of |:setglobal|, use
+--- `vim.opt_global`.
+--- 
+ +--- @class vim.Option local Option = {} -- luacheck: no unused --- Returns a Lua-representation of the option. Boolean, number and string @@ -856,9 +847,7 @@ local Option = {} -- luacheck: no unused --- print("J is enabled!") --- end --- ``` ---- ---@return string|integer|boolean|nil value of option ----@diagnostic disable-next-line:unused-local used for gen_vimdoc function Option:get() end --- Append a value to string-style options. See |:set+=| @@ -869,7 +858,6 @@ function Option:get() end --- vim.opt.formatoptions:append('j') --- vim.opt.formatoptions = vim.opt.formatoptions + 'j' --- ``` ---- ---@param value string Value to append ---@diagnostic disable-next-line:unused-local used for gen_vimdoc function Option:append(value) end -- luacheck: no unused @@ -882,7 +870,6 @@ function Option:append(value) end -- luacheck: no unused --- vim.opt.wildignore:prepend('*.o') --- vim.opt.wildignore = vim.opt.wildignore ^ '*.o' --- ``` ---- ---@param value string Value to prepend ---@diagnostic disable-next-line:unused-local used for gen_vimdoc function Option:prepend(value) end -- luacheck: no unused @@ -895,7 +882,6 @@ function Option:prepend(value) end -- luacheck: no unused --- vim.opt.wildignore:remove('*.pyc') --- vim.opt.wildignore = vim.opt.wildignore - '*.pyc' --- ``` ---- ---@param value string Value to remove ---@diagnostic disable-next-line:unused-local used for gen_vimdoc function Option:remove(value) end -- luacheck: no unused diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 91f91b5879..49165c4db9 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -70,6 +70,7 @@ local M = {} --- @field linehl? table --- @field texthl? table +--- @nodoc --- @enum vim.diagnostic.Severity M.severity = { ERROR = 1, @@ -107,6 +108,7 @@ local global_diagnostic_options = { --- @field show? fun(namespace: integer, bufnr: integer, diagnostics: vim.Diagnostic[], opts?: vim.diagnostic.OptsResolved) --- @field hide? fun(namespace:integer, bufnr:integer) +--- @nodoc --- @type table M.handlers = setmetatable({}, { __newindex = function(t, name, handler) @@ -731,71 +733,71 @@ end --- - `function`: Function with signature (namespace, bufnr) that returns any of the above. --- ---@param opts vim.diagnostic.Opts? (table?) When omitted or "nil", retrieve the current ---- configuration. Otherwise, a configuration table with the following keys: +--- configuration. Otherwise, a configuration table with the following keys: --- - underline: (default true) Use underline for diagnostics. Options: ---- * severity: Only underline diagnostics matching the given ---- severity |diagnostic-severity| +--- * severity: Only underline diagnostics matching the given +--- severity |diagnostic-severity| --- - virtual_text: (default true) Use virtual text for diagnostics. If multiple diagnostics ---- are set for a namespace, one prefix per diagnostic + the last diagnostic ---- message are shown. In addition to the options listed below, the ---- "virt_text" options of |nvim_buf_set_extmark()| may also be used here ---- (e.g. "virt_text_pos" and "hl_mode"). ---- Options: ---- * severity: Only show virtual text for diagnostics matching the given ---- severity |diagnostic-severity| ---- * source: (boolean or string) Include the diagnostic source in virtual ---- text. Use "if_many" to only show sources if there is more than ---- one diagnostic source in the buffer. Otherwise, any truthy value ---- means to always show the diagnostic source. ---- * spacing: (number) Amount of empty spaces inserted at the beginning ---- of the virtual text. ---- * prefix: (string or function) prepend diagnostic message with prefix. ---- If a function, it must have the signature (diagnostic, i, total) ---- -> string, where {diagnostic} is of type |diagnostic-structure|, ---- {i} is the index of the diagnostic being evaluated, and {total} ---- is the total number of diagnostics for the line. This can be ---- used to render diagnostic symbols or error codes. ---- * suffix: (string or function) Append diagnostic message with suffix. ---- If a function, it must have the signature (diagnostic) -> ---- string, where {diagnostic} is of type |diagnostic-structure|. ---- This can be used to render an LSP diagnostic error code. ---- * format: (function) A function that takes a diagnostic as input and ---- returns a string. The return value is the text used to display ---- the diagnostic. Example: ----
lua
----                         function(diagnostic)
----                           if diagnostic.severity == vim.diagnostic.severity.ERROR then
----                             return string.format("E: %s", diagnostic.message)
----                           end
----                           return diagnostic.message
----                         end
----                       
+--- are set for a namespace, one prefix per diagnostic + the last diagnostic +--- message are shown. In addition to the options listed below, the +--- "virt_text" options of |nvim_buf_set_extmark()| may also be used here +--- (e.g. "virt_text_pos" and "hl_mode"). +--- Options: +--- * severity: Only show virtual text for diagnostics matching the given +--- severity |diagnostic-severity| +--- * source: (boolean or string) Include the diagnostic source in virtual +--- text. Use "if_many" to only show sources if there is more than +--- one diagnostic source in the buffer. Otherwise, any truthy value +--- means to always show the diagnostic source. +--- * spacing: (number) Amount of empty spaces inserted at the beginning +--- of the virtual text. +--- * prefix: (string or function) prepend diagnostic message with prefix. +--- If a function, it must have the signature (diagnostic, i, total) +--- -> string, where {diagnostic} is of type |diagnostic-structure|, +--- {i} is the index of the diagnostic being evaluated, and {total} +--- is the total number of diagnostics for the line. This can be +--- used to render diagnostic symbols or error codes. +--- * suffix: (string or function) Append diagnostic message with suffix. +--- If a function, it must have the signature (diagnostic) -> +--- string, where {diagnostic} is of type |diagnostic-structure|. +--- This can be used to render an LSP diagnostic error code. +--- * format: (function) A function that takes a diagnostic as input and +--- returns a string. The return value is the text used to display +--- the diagnostic. Example: +--- ```lua +--- function(diagnostic) +--- if diagnostic.severity == vim.diagnostic.severity.ERROR then +--- return string.format("E: %s", diagnostic.message) +--- end +--- return diagnostic.message +--- end +--- ``` --- - signs: (default true) Use signs for diagnostics |diagnostic-signs|. Options: ---- * severity: Only show signs for diagnostics matching the given ---- severity |diagnostic-severity| ---- * priority: (number, default 10) Base priority to use for signs. When ---- {severity_sort} is used, the priority of a sign is adjusted based on ---- its severity. Otherwise, all signs use the same priority. ---- * text: (table) A table mapping |diagnostic-severity| to the sign text ---- to display in the sign column. The default is to use "E", "W", "I", and "H" ---- for errors, warnings, information, and hints, respectively. Example: ----
lua
----                       vim.diagnostic.config({
----                         signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } }
----                       })
----                   
---- * numhl: (table) A table mapping |diagnostic-severity| to the highlight ---- group used for the line number where the sign is placed. ---- * linehl: (table) A table mapping |diagnostic-severity| to the highlight group ---- used for the whole line the sign is placed in. +--- * severity: Only show signs for diagnostics matching the given +--- severity |diagnostic-severity| +--- * priority: (number, default 10) Base priority to use for signs. When +--- {severity_sort} is used, the priority of a sign is adjusted based on +--- its severity. Otherwise, all signs use the same priority. +--- * text: (table) A table mapping |diagnostic-severity| to the sign text +--- to display in the sign column. The default is to use "E", "W", "I", and "H" +--- for errors, warnings, information, and hints, respectively. Example: +--- ```lua +--- vim.diagnostic.config({ +--- signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } } +--- }) +--- ``` +--- * numhl: (table) A table mapping |diagnostic-severity| to the highlight +--- group used for the line number where the sign is placed. +--- * linehl: (table) A table mapping |diagnostic-severity| to the highlight group +--- used for the whole line the sign is placed in. --- - float: Options for floating windows. See |vim.diagnostic.open_float()|. --- - update_in_insert: (default false) Update diagnostics in Insert mode (if false, --- diagnostics are updated on InsertLeave) --- - severity_sort: (default false) Sort diagnostics by severity. This affects the order in ---- which signs and virtual text are displayed. When true, higher severities ---- are displayed before lower severities (e.g. ERROR is displayed before WARN). ---- Options: ---- * reverse: (boolean) Reverse sort order +--- which signs and virtual text are displayed. When true, higher severities +--- are displayed before lower severities (e.g. ERROR is displayed before WARN). +--- Options: +--- * reverse: (boolean) Reverse sort order --- ---@param namespace integer? Update the options for the given namespace. When omitted, update the --- global diagnostic options. @@ -1090,8 +1092,8 @@ M.handlers.signs = { api.nvim_create_namespace(string.format('%s/diagnostic/signs', ns.name)) end - --- Handle legacy diagnostic sign definitions - --- These were deprecated in 0.10 and will be removed in 0.12 + -- Handle legacy diagnostic sign definitions + -- These were deprecated in 0.10 and will be removed in 0.12 if opts.signs and not opts.signs.text and not opts.signs.numhl and not opts.signs.texthl then for _, v in ipairs({ 'Error', 'Warn', 'Info', 'Hint' }) do local name = string.format('DiagnosticSign%s', v) @@ -1543,7 +1545,8 @@ end --- Overrides the setting from |vim.diagnostic.config()|. --- - suffix: Same as {prefix}, but appends the text to the diagnostic instead of --- prepending it. Overrides the setting from |vim.diagnostic.config()|. ----@return integer?, integer?: ({float_bufnr}, {win_id}) +---@return integer? float_bufnr +---@return integer? win_id function M.open_float(opts, ...) -- Support old (bufnr, opts) signature local bufnr --- @type integer? diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index b43072a725..e7971d8916 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -2279,9 +2279,9 @@ end --- Perform filetype detection. --- --- The filetype can be detected using one of three methods: ---- 1. Using an existing buffer ---- 2. Using only a file name ---- 3. Using only file contents +--- 1. Using an existing buffer +--- 2. Using only a file name +--- 3. Using only file contents --- --- Of these, option 1 provides the most accurate result as it uses both the buffer's filename and --- (optionally) the buffer contents. Options 2 and 3 can be used without an existing buffer, but diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index 22612a7255..0af5fc4f30 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -320,7 +320,7 @@ end --- Normalize a path to a standard format. A tilde (~) character at the --- beginning of the path is expanded to the user's home directory and any ---- backslash (\\) characters are converted to forward slashes (/). Environment +--- backslash (\) characters are converted to forward slashes (/). Environment --- variables are also expanded. --- --- Examples: diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua index b055cce49d..effe280dee 100644 --- a/runtime/lua/vim/highlight.lua +++ b/runtime/lua/vim/highlight.lua @@ -1,4 +1,4 @@ ----@defgroup vim.highlight +---@brief --- --- Nvim includes a function for highlighting a selection on yank. --- @@ -19,18 +19,19 @@ --- ```vim --- au TextYankPost * silent! lua vim.highlight.on_yank {on_visual=false} --- ``` +--- local api = vim.api local M = {} --- Table with default priorities used for highlighting: ---- - `syntax`: `50`, used for standard syntax highlighting ---- - `treesitter`: `100`, used for treesitter-based highlighting ---- - `semantic_tokens`: `125`, used for LSP semantic token highlighting ---- - `diagnostics`: `150`, used for code analysis such as diagnostics ---- - `user`: `200`, used for user-triggered highlights such as LSP document ---- symbols or `on_yank` autocommands +--- - `syntax`: `50`, used for standard syntax highlighting +--- - `treesitter`: `100`, used for treesitter-based highlighting +--- - `semantic_tokens`: `125`, used for LSP semantic token highlighting +--- - `diagnostics`: `150`, used for code analysis such as diagnostics +--- - `user`: `200`, used for user-triggered highlights such as LSP document +--- symbols or `on_yank` autocommands M.priorities = { syntax = 50, treesitter = 100, diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index d720745110..798428014d 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -1,4 +1,4 @@ ----@defgroup vim.iter +--- @brief --- --- \*vim.iter()\* is an interface for |iterable|s: it wraps a table or function argument into an --- \*Iter\* object with methods (such as |Iter:filter()| and |Iter:map()|) that transform the @@ -66,6 +66,7 @@ ---@class IterMod ---@operator call:Iter + local M = {} ---@class Iter @@ -599,7 +600,7 @@ end --- -- 12 --- --- ``` ---- +---@param f any ---@return any function Iter.find(self, f) if type(f) ~= 'function' then @@ -645,6 +646,7 @@ end --- ---@see Iter.find --- +---@param f any ---@return any ---@diagnostic disable-next-line: unused-local function Iter.rfind(self, f) -- luacheck: no unused args @@ -724,6 +726,7 @@ function Iter.nextback(self) -- luacheck: no unused args error('nextback() requires a list-like table') end +--- @nodoc function ListIter.nextback(self) if self._head ~= self._tail then local inc = self._head < self._tail and 1 or -1 @@ -754,6 +757,7 @@ function Iter.peekback(self) -- luacheck: no unused args error('peekback() requires a list-like table') end +---@nodoc function ListIter.peekback(self) if self._head ~= self._tail then local inc = self._head < self._tail and 1 or -1 diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua index 8e4e123fe0..84e9b4197d 100644 --- a/runtime/lua/vim/keymap.lua +++ b/runtime/lua/vim/keymap.lua @@ -90,6 +90,8 @@ end --- vim.keymap.del({'n', 'i', 'v'}, 'w', { buffer = 5 }) --- ``` --- +---@param modes string|string[] +---@param lhs string ---@param opts table|nil A table of optional arguments: --- - "buffer": (integer|boolean) Remove a mapping from the given buffer. --- When `0` or `true`, use the current buffer. diff --git a/runtime/lua/vim/loader.lua b/runtime/lua/vim/loader.lua index ec99e417c2..5f3da55544 100644 --- a/runtime/lua/vim/loader.lua +++ b/runtime/lua/vim/loader.lua @@ -190,7 +190,6 @@ function Loader.loader_lib(modname) local sysname = uv.os_uname().sysname:lower() or '' local is_win = sysname:find('win', 1, true) and not sysname:find('darwin', 1, true) local ret = M.find(modname, { patterns = is_win and { '.dll' } or { '.so' } })[1] - ---@type function?, string? if ret then -- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is -- a) strip prefix up to and including the first dash, if any @@ -208,15 +207,13 @@ end --- `loadfile` using the cache --- Note this has the mode and env arguments which is supported by LuaJIT and is 5.1 compatible. ---@param filename? string ----@param mode? "b"|"t"|"bt" +---@param _mode? "b"|"t"|"bt" ---@param env? table ---@return function?, string? error_message ---@private --- luacheck: ignore 312 -function Loader.loadfile(filename, mode, env) +function Loader.loadfile(filename, _mode, env) -- ignore mode, since we byte-compile the Lua source files - mode = nil - return Loader.load(normalize(filename), { mode = mode, env = env }) + return Loader.load(normalize(filename), { env = env }) end --- Checks whether two cache hashes are the same based on: @@ -273,14 +270,14 @@ end --- Finds Lua modules for the given module name. ---@param modname string Module name, or `"*"` to find the top-level modules instead ----@param opts? ModuleFindOpts (table|nil) Options for finding a module: +---@param opts? ModuleFindOpts (table) Options for finding a module: --- - rtp: (boolean) Search for modname in the runtime path (defaults to `true`) --- - paths: (string[]) Extra paths to search for modname (defaults to `{}`) --- - patterns: (string[]) List of patterns to use when searching for modules. --- A pattern is a string added to the basename of the Lua module being searched. --- (defaults to `{"/init.lua", ".lua"}`) --- - all: (boolean) Return all matches instead of just the first one (defaults to `false`) ----@return ModuleInfo[] (list) A list of results with the following properties: +---@return ModuleInfo[] (table) A list of results with the following properties: --- - modpath: (string) the path to the module --- - modname: (string) the name of the module --- - stat: (table|nil) the fs_stat of the module path. Won't be returned for `modname="*"` diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 3a74c3ee90..19497e40dc 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -206,99 +206,96 @@ end --- |vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|. --- --- - Methods: ---- ---- - request(method, params, [handler], bufnr) ---- Sends a request to the server. ---- This is a thin wrapper around {client.rpc.request} with some additional ---- checking. ---- If {handler} is not specified, If one is not found there, then an error will occur. ---- Returns: {status}, {[client_id]}. {status} is a boolean indicating if ---- the notification was successful. If it is `false`, then it will always ---- be `false` (the client has shutdown). ---- If {status} is `true`, the function returns {request_id} as the second ---- result. You can use this with `client.cancel_request(request_id)` ---- to cancel the request. ---- ---- - request_sync(method, params, timeout_ms, bufnr) ---- Sends a request to the server and synchronously waits for the response. ---- This is a wrapper around {client.request} ---- Returns: { err=err, result=result }, a dictionary, where `err` and `result` come from ---- the |lsp-handler|. On timeout, cancel or error, returns `(nil, err)` where `err` is a ---- string describing the failure reason. If the request was unsuccessful returns `nil`. ---- ---- - notify(method, params) ---- Sends a notification to an LSP server. ---- Returns: a boolean to indicate if the notification was successful. If ---- it is false, then it will always be false (the client has shutdown). ---- ---- - cancel_request(id) ---- Cancels a request with a given request id. ---- Returns: same as `notify()`. ---- ---- - stop([force]) ---- Stops 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() ---- Checks whether a client is stopped. ---- Returns: true if the client is fully stopped. ---- ---- - on_attach(client, bufnr) ---- Runs the on_attach function from the client's config if it was defined. ---- Useful for buffer-local setup. ---- ---- - supports_method(method, [opts]): boolean ---- Checks if a client supports a given method. ---- Always returns true for unknown off-spec methods. ---- [opts] is a optional `{bufnr?: integer}` table. ---- Some language server capabilities can be file specific. +--- - request(method, params, [handler], bufnr) +--- Sends a request to the server. +--- This is a thin wrapper around {client.rpc.request} with some additional +--- checking. +--- If {handler} is not specified, If one is not found there, then an error will occur. +--- Returns: {status}, {[client_id]}. {status} is a boolean indicating if +--- the notification was successful. If it is `false`, then it will always +--- be `false` (the client has shutdown). +--- If {status} is `true`, the function returns {request_id} as the second +--- result. You can use this with `client.cancel_request(request_id)` +--- to cancel the request. +--- +--- - request_sync(method, params, timeout_ms, bufnr) +--- Sends a request to the server and synchronously waits for the response. +--- This is a wrapper around {client.request} +--- Returns: { err=err, result=result }, a dictionary, where `err` and `result` come from +--- the |lsp-handler|. On timeout, cancel or error, returns `(nil, err)` where `err` is a +--- string describing the failure reason. If the request was unsuccessful returns `nil`. +--- +--- - notify(method, params) +--- Sends a notification to an LSP server. +--- Returns: a boolean to indicate if the notification was successful. If +--- it is false, then it will always be false (the client has shutdown). +--- +--- - cancel_request(id) +--- Cancels a request with a given request id. +--- Returns: same as `notify()`. +--- +--- - stop([force]) +--- Stops 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() +--- Checks whether a client is stopped. +--- Returns: true if the client is fully stopped. +--- +--- - on_attach(client, bufnr) +--- Runs the on_attach function from the client's config if it was defined. +--- Useful for buffer-local setup. +--- +--- - supports_method(method, [opts]): boolean +--- Checks if a client supports a given method. +--- Always returns true for unknown off-spec methods. +--- [opts] is a optional `{bufnr?: integer}` table. +--- Some language server capabilities can be file specific. --- --- - Members ---- - {id} (number): The id allocated to the client. +--- - {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. +--- - {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. --- ---- - {rpc} (table): RPC client object, for low level interaction with the ---- client. See |vim.lsp.rpc.start()|. +--- - {rpc} (table): RPC client object, for low level interaction with the +--- client. See |vim.lsp.rpc.start()|. --- ---- - {offset_encoding} (string): The encoding used for communicating ---- with the server. You can modify this in the `config`'s `on_init` method ---- before text is sent to the server. +--- - {offset_encoding} (string): The encoding used for communicating +--- with the server. You can modify this in the `config`'s `on_init` method +--- before text is sent to the server. --- ---- - {handlers} (table): The handlers used by the client as described in |lsp-handler|. +--- - {handlers} (table): The handlers used by the client as described in |lsp-handler|. --- ---- - {commands} (table): Table of command name to function which is called if ---- any LSP action (code action, code lenses, ...) triggers the command. ---- Client commands take precedence over the global command registry. +--- - {commands} (table): Table of command name to function which is called if +--- any LSP action (code action, code lenses, ...) triggers the command. +--- Client commands take precedence over the global command registry. --- ---- - {requests} (table): The current pending requests in flight ---- to the server. Entries are key-value pairs with the key ---- being the request ID while the value is a table with `type`, ---- `bufnr`, and `method` key-value pairs. `type` is either "pending" ---- for an active request, or "cancel" for a cancel request. It will ---- be "complete" ephemerally while executing |LspRequest| autocmds ---- when replies are received from the server. +--- - {requests} (table): The current pending requests in flight +--- to the server. Entries are key-value pairs with the key +--- being the request ID while the value is a table with `type`, +--- `bufnr`, and `method` key-value pairs. `type` is either "pending" +--- for an active request, or "cancel" for a cancel request. It will +--- be "complete" ephemerally while executing |LspRequest| autocmds +--- when replies are received from the server. --- ---- - {config} (table): Reference of the table that was passed by the user ---- to |vim.lsp.start_client()|. +--- - {config} (table): Reference 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. +--- - {server_capabilities} (table): Response from the server sent on +--- `initialize` describing the server's capabilities. --- ---- - {progress} A ring buffer (|vim.ringbuf()|) containing progress messages ---- sent by the server. +--- - {progress} A ring buffer (|vim.ringbuf()|) containing progress messages +--- sent by the server. --- ---- - {settings} Map with language server specific settings. ---- See {config} in |vim.lsp.start_client()| +--- - {settings} Map with language server specific settings. +--- See {config} in |vim.lsp.start_client()| --- ---- - {flags} A table with flags for the client. See {config} in |vim.lsp.start_client()| -function lsp.client() - error() -end +--- - {flags} A table with flags for the client. See {config} in |vim.lsp.start_client()| +lsp.client = nil --- @class lsp.StartOpts --- @field reuse_client fun(client: lsp.Client, config: table): boolean @@ -581,9 +578,9 @@ end --- spawn. Must be specified using a table. --- Non-string values are coerced to string. --- Example: ----
----                   { PORT = 8080; HOST = "0.0.0.0"; }
----       
+--- ``` +--- { PORT = 8080; HOST = "0.0.0.0"; } +--- ``` --- --- - detached: (boolean, default true) Daemonize the server process so that it runs in a --- separate process group from Nvim. Nvim will shutdown the process on exit, but if Nvim fails to @@ -598,8 +595,9 @@ end --- \|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.empty_dict()|, else it will be encoded as an ---- array. +--- +--- - Note: To send an empty dictionary use |vim.empty_dict()|, else it will be encoded as an +--- array. --- --- - handlers: Map of language server method names to |lsp-handler| --- @@ -645,9 +643,9 @@ end --- --- - 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 +--- - 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. @@ -656,13 +654,13 @@ end --- server in the initialize request. Invalid/empty values will default to "off" --- --- - flags: A table with flags for the client. The current (experimental) flags are: ---- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits ---- - debounce_text_changes (number, default 150): Debounce didChange ---- notifications to the server by the given number in milliseconds. No debounce ---- occurs if nil ---- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to ---- exit cleanly after sending the "shutdown" request before sending kill -15. ---- If set to false, nvim exits immediately after sending the "shutdown" request to the server. +--- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits +--- - debounce_text_changes (number, default 150): Debounce didChange +--- notifications to the server by the given number in milliseconds. No debounce +--- occurs if nil +--- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to +--- exit cleanly after sending the "shutdown" request before sending kill -15. +--- If set to false, nvim exits immediately after sending the "shutdown" request to the server. --- --- - root_dir: (string) Directory where the LSP --- server will base its workspaceFolders, rootUri, and rootPath @@ -1239,7 +1237,7 @@ end --- --- Currently only supports a single client. This can be set via --- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach` ---- via ``vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'``. +--- via `vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`. --- ---@param opts table options for customizing the formatting expression which takes the --- following optional keys: diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 7fc5286a78..d2e92de083 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -12,7 +12,7 @@ local M = {} ---@param method (string) LSP method name ---@param params (table|nil) Parameters to send to the server ---@param handler (function|nil) See |lsp-handler|. Follows |lsp-handler-resolution| --- +--- ---@return table client_request_ids Map of client-id:request-id pairs ---for all successful requests. ---@return function _cancel_all_requests Function which can be used to @@ -172,12 +172,13 @@ end --- --- - filter (function|nil): --- Predicate used to filter clients. Receives a client as argument and must return a ---- boolean. Clients matching the predicate are included. Example:
lua
----                     -- Never request typescript-language-server for formatting
----                     vim.lsp.buf.format {
----                       filter = function(client) return client.name ~= "tsserver" end
----                     }
----         
+--- boolean. Clients matching the predicate are included. Example: +--- ```lua +--- -- Never request typescript-language-server for formatting +--- vim.lsp.buf.format { +--- filter = function(client) return client.name ~= "tsserver" end +--- } +--- ``` --- --- - async boolean|nil --- If true the method won't block. Defaults to false. @@ -472,6 +473,7 @@ end --- Add the folder at path to the workspace folders. If {path} is --- not provided, the user will be prompted for a path using |input()|. +--- @param workspace_folder? string function M.add_workspace_folder(workspace_folder) workspace_folder = workspace_folder or npcall(vim.fn.input, 'Workspace Folder: ', vim.fn.expand('%:p:h'), 'dir') @@ -511,6 +513,7 @@ end --- Remove the folder at path from the workspace folders. If --- {path} is not provided, the user will be prompted for --- a path using |input()|. +--- @param workspace_folder? string function M.remove_workspace_folder(workspace_folder) workspace_folder = workspace_folder or npcall(vim.fn.input, 'Workspace Folder: ', vim.fn.expand('%:p:h')) @@ -725,15 +728,15 @@ end --- ---@param options table|nil Optional table which holds the following optional fields: --- - context: (table|nil) ---- Corresponds to `CodeActionContext` of the LSP specification: ---- - diagnostics (table|nil): ---- LSP `Diagnostic[]`. Inferred from the current ---- position if not provided. ---- - only (table|nil): ---- List of LSP `CodeActionKind`s used to filter the code actions. ---- Most language servers support values like `refactor` ---- or `quickfix`. ---- - triggerKind (number|nil): The reason why code actions were requested. +--- Corresponds to `CodeActionContext` of the LSP specification: +--- - diagnostics (table|nil): +--- LSP `Diagnostic[]`. Inferred from the current +--- position if not provided. +--- - only (table|nil): +--- List of LSP `CodeActionKind`s used to filter the code actions. +--- Most language servers support values like `refactor` +--- or `quickfix`. +--- - triggerKind (number|nil): The reason why code actions were requested. --- - filter: (function|nil) --- Predicate taking an `CodeAction` and returning a boolean. --- - apply: (boolean|nil) diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index 966c7f4d03..7aed6f99e3 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -258,6 +258,8 @@ end --- |lsp-handler| for the method `textDocument/codeLens` --- +---@param err lsp.ResponseError? +---@param result lsp.CodeLens[] ---@param ctx lsp.HandlerContext function M.on_codelens(err, result, ctx, _) if err then diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 33051ab61c..1fa67fc473 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -1,5 +1,3 @@ ----@brief lsp-diagnostic - local protocol = require('vim.lsp.protocol') local ms = protocol.Methods @@ -287,6 +285,7 @@ end --- ) --- ``` --- +---@param _ lsp.ResponseError? ---@param result lsp.PublishDiagnosticsParams ---@param ctx lsp.HandlerContext ---@param config? vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|). @@ -319,6 +318,7 @@ end --- ) --- ``` --- +---@param _ lsp.ResponseError? ---@param result lsp.DocumentDiagnosticReport ---@param ctx lsp.HandlerContext ---@param config table Configuration table (see |vim.diagnostic.config()|). diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index a9da812231..781d720486 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -368,6 +368,8 @@ end --- ) --- ``` --- +---@param _ lsp.ResponseError? +---@param result lsp.Hover ---@param ctx lsp.HandlerContext ---@param config table Configuration table. --- - border: (default=nil) @@ -464,7 +466,8 @@ M[ms.textDocument_implementation] = location_handler --- ) --- ``` --- ----@param result table Response from the language server +---@param _ lsp.ResponseError? +---@param result lsp.SignatureHelp Response from the language server ---@param ctx lsp.HandlerContext Client context ---@param config table Configuration table. --- - border: (default=nil) diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua index a9d49bc8f4..018003bb81 100644 --- a/runtime/lua/vim/lsp/log.lua +++ b/runtime/lua/vim/lsp/log.lua @@ -165,7 +165,7 @@ end --- Checks whether the level is sufficient for logging. ---@param level integer log level ----@returns (bool) true if would log, false if not +---@return bool : true if would log, false if not function log.should_log(level) return level >= current_log_level end diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index e849bb4f2a..1455ab51fa 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -273,8 +273,6 @@ end ---@field notify_reply_callbacks table dict of message_id to callback ---@field transport vim.lsp.rpc.Transport ---@field dispatchers vim.lsp.rpc.Dispatchers - ----@class vim.lsp.rpc.Client local Client = {} ---@private diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua index 62fa0b33f4..936579e003 100644 --- a/runtime/lua/vim/lsp/sync.lua +++ b/runtime/lua/vim/lsp/sync.lua @@ -53,7 +53,7 @@ local str_utf_end = vim.str_utf_end ---@param line string the line to index into ---@param byte integer the byte idx ---@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8) ---@returns integer the utf idx for the given encoding +---@return integer utf_idx for the given encoding local function byte_to_utf(line, byte, offset_encoding) -- convert to 0 based indexing for str_utfindex byte = byte - 1 @@ -204,7 +204,7 @@ end --- Normalized to the next codepoint. --- prev_end_range is the text range sent to the server representing the changed region. --- curr_end_range is the text that should be collected and sent to the server. --- +--- ---@param prev_lines string[] list of lines ---@param curr_lines string[] list of lines ---@param start_range vim.lsp.sync.Range diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index b60135f851..e371cb0e15 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -574,6 +574,7 @@ end --- ---@param text_document_edit table: a `TextDocumentEdit` object ---@param index integer: Optional index of the edit, if from a list of edits (or nil, if not from a list) +---@param offset_encoding? string ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit function M.apply_text_document_edit(text_document_edit, index, offset_encoding) local text_document = text_document_edit.textDocument @@ -770,7 +771,7 @@ end --- ---@param workspace_edit table `WorkspaceEdit` ---@param offset_encoding string utf-8|utf-16|utf-32 (required) ---see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit +---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit function M.apply_workspace_edit(workspace_edit, offset_encoding) if offset_encoding == nil then vim.notify_once( @@ -1130,6 +1131,7 @@ end --- - for LocationLink, targetRange is shown (e.g., body of function definition) --- ---@param location table a single `Location` or `LocationLink` +---@param opts table ---@return integer|nil buffer id of float window ---@return integer|nil window id of float window function M.preview_location(location, opts) @@ -1243,6 +1245,7 @@ end --- --- If you want to open a popup with fancy markdown, use `open_floating_preview` instead --- +---@param bufnr integer ---@param contents table of lines to show in window ---@param opts table with optional fields --- - height of floating window @@ -1603,7 +1606,7 @@ end ---@param contents table of lines to show in window ---@param syntax string of syntax to set for opened buffer ---@param opts table with optional fields (additional keys are filtered with |vim.lsp.util.make_floating_popup_options()| ---- before they are passed on to |nvim_open_win()|) +--- before they are passed on to |nvim_open_win()|) --- - height: (integer) height of floating window --- - width: (integer) width of floating window --- - wrap: (boolean, default true) wrap long lines @@ -1868,6 +1871,7 @@ end --- Converts symbols to quickfix list items. --- ---@param symbols table DocumentSymbol[] or SymbolInformation[] +---@param bufnr integer function M.symbols_to_items(symbols, bufnr) local function _symbols_to_items(_symbols, _items, _bufnr) for _, symbol in ipairs(_symbols) do diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 5cf8390843..83fdfede89 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -6,6 +6,7 @@ -- or the test suite. (Eventually the test suite will be run in a worker process, -- so this wouldn't be a separate case to consider) +---@nodoc ---@diagnostic disable-next-line: lowercase-global vim = vim or {} @@ -191,8 +192,8 @@ end --- ---@param s string String to split ---@param sep string Separator or pattern ----@param opts (table|nil) Keyword arguments |kwargs| accepted by |vim.gsplit()| ----@return string[] List of split components +---@param opts? table Keyword arguments |kwargs| accepted by |vim.gsplit()| +---@return string[] : List of split components function vim.split(s, sep, opts) local t = {} for c in vim.gsplit(s, sep, opts) do @@ -206,9 +207,9 @@ end --- ---@see From https://github.com/premake/premake-core/blob/master/src/base/table.lua --- ----@generic T: table +---@generic T ---@param t table (table) Table ----@return T[] (list) List of keys +---@return T[] : List of keys function vim.tbl_keys(t) vim.validate({ t = { t, 't' } }) --- @cast t table @@ -225,7 +226,7 @@ end --- ---@generic T ---@param t table (table) Table ----@return T[] (list) List of values +---@return T[] : List of values function vim.tbl_values(t) vim.validate({ t = { t, 't' } }) @@ -243,7 +244,7 @@ end ---@generic T ---@param func fun(value: T): any (function) Function ---@param t table (table) Table ----@return table Table of transformed values +---@return table : Table of transformed values function vim.tbl_map(func, t) vim.validate({ func = { func, 'c' }, t = { t, 't' } }) --- @cast t table @@ -260,7 +261,7 @@ end ---@generic T ---@param func fun(value: T): boolean (function) Function ---@param t table (table) Table ----@return T[] (table) Table of filtered values +---@return T[] : Table of filtered values function vim.tbl_filter(func, t) vim.validate({ func = { func, 'c' }, t = { t, 't' } }) --- @cast t table @@ -401,7 +402,7 @@ end --- - "keep": use value from the leftmost map --- - "force": use value from the rightmost map ---@param ... table Two or more tables ----@return table Merged table +---@return table : Merged table function vim.tbl_extend(behavior, ...) return tbl_extend(behavior, false, ...) end @@ -456,7 +457,7 @@ end --- Add the reverse lookup values to an existing table. --- For example: ---- ``tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }`` +--- `tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }` --- --- Note that this *modifies* the input. ---@param o table Table to add the reverse to @@ -493,7 +494,7 @@ end --- ---@param o table Table to index ---@param ... any Optional keys (0 or more, variadic) via which to index the table ----@return any Nested value indexed by key (if it exists), else nil +---@return any : Nested value indexed by key (if it exists), else nil function vim.tbl_get(o, ...) local keys = { ... } if #keys == 0 then @@ -519,8 +520,8 @@ end ---@generic T: table ---@param dst T List which will be modified and appended to ---@param src table List from which values will be inserted ----@param start (integer|nil) Start index on src. Defaults to 1 ----@param finish (integer|nil) Final index on src. Defaults to `#src` +---@param start integer? Start index on src. Defaults to 1 +---@param finish integer? Final index on src. Defaults to `#src` ---@return T dst function vim.list_extend(dst, src, start, finish) vim.validate({ @@ -666,7 +667,7 @@ end --- ---@see https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua ---@param t table Table ----@return integer Number of non-nil values in table +---@return integer : Number of non-nil values in table function vim.tbl_count(t) vim.validate({ t = { t, 't' } }) --- @cast t table @@ -681,10 +682,10 @@ end --- Creates a copy of a table containing only elements from start to end (inclusive) --- ---@generic T ----@param list T[] (list) Table +---@param list T[] Table ---@param start integer|nil Start range of slice ---@param finish integer|nil End range of slice ----@return T[] (list) Copy of table sliced from start to finish (inclusive) +---@return T[] Copy of table sliced from start to finish (inclusive) function vim.list_slice(list, start, finish) local new_list = {} --- @type `T`[] for i = start or 1, finish or #list do @@ -840,38 +841,37 @@ do --- Usage example: --- --- ```lua - --- function user.new(name, age, hobbies) - --- vim.validate{ - --- name={name, 'string'}, - --- age={age, 'number'}, - --- hobbies={hobbies, 'table'}, - --- } - --- ... - --- end + --- function user.new(name, age, hobbies) + --- vim.validate{ + --- name={name, 'string'}, + --- age={age, 'number'}, + --- hobbies={hobbies, 'table'}, + --- } + --- ... + --- end --- ``` --- --- Examples with explicit argument values (can be run directly): --- --- ```lua - --- vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}} - --- --> NOP (success) + --- vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}} + --- --> NOP (success) --- - --- vim.validate{arg1={1, 'table'}} - --- --> error('arg1: expected table, got number') + --- vim.validate{arg1={1, 'table'}} + --- --> error('arg1: expected table, got number') --- - --- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}} - --- --> error('arg1: expected even number, got 3') + --- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}} + --- --> error('arg1: expected even number, got 3') --- ``` --- --- If multiple types are valid they can be given as a list. --- --- ```lua - --- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}} - --- -- NOP (success) - --- - --- vim.validate{arg1={1, {'string', 'table'}}} - --- -- error('arg1: expected string|table, got number') + --- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}} + --- -- NOP (success) --- + --- vim.validate{arg1={1, {'string', 'table'}}} + --- -- error('arg1: expected string|table, got number') --- ``` --- ---@param opt table (table) Names of parameters to validate. Each key is a parameter @@ -989,19 +989,19 @@ do --- Once the buffer is full, adding a new entry overrides the oldest entry. --- --- ```lua - --- local ringbuf = vim.ringbuf(4) - --- ringbuf:push("a") - --- ringbuf:push("b") - --- ringbuf:push("c") - --- ringbuf:push("d") - --- ringbuf:push("e") -- overrides "a" - --- print(ringbuf:pop()) -- returns "b" - --- print(ringbuf:pop()) -- returns "c" + --- local ringbuf = vim.ringbuf(4) + --- ringbuf:push("a") + --- ringbuf:push("b") + --- ringbuf:push("c") + --- ringbuf:push("d") + --- ringbuf:push("e") -- overrides "a" + --- print(ringbuf:pop()) -- returns "b" + --- print(ringbuf:pop()) -- returns "c" --- - --- -- Can be used as iterator. Pops remaining items: - --- for val in ringbuf do - --- print(val) - --- end + --- -- Can be used as iterator. Pops remaining items: + --- for val in ringbuf do + --- print(val) + --- end --- ``` --- --- Returns a Ringbuf instance with the following methods: diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua index 7e37d84393..09b7576d97 100644 --- a/runtime/lua/vim/snippet.lua +++ b/runtime/lua/vim/snippet.lua @@ -245,8 +245,6 @@ function Session:set_group_gravity(index, right_gravity) end end ---- @class vim.snippet.Snippet ---- @field private _session? vim.snippet.Session local M = { session = nil } --- Displays the choices for the given tabstop as completion items. diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index e2197168f0..9b69f95f54 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -432,7 +432,7 @@ end --- Can be used in an ftplugin or FileType autocommand. --- --- Note: By default, disables regex syntax highlighting, which may be required for some plugins. ---- In this case, add ``vim.bo.syntax = 'on'`` after the call to `start`. +--- In this case, add `vim.bo.syntax = 'on'` after the call to `start`. --- --- Example: --- diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua index 556c910feb..6ec997eb4a 100644 --- a/runtime/lua/vim/treesitter/_query_linter.lua +++ b/runtime/lua/vim/treesitter/_query_linter.lua @@ -197,7 +197,7 @@ function M.clear(buf) end --- @private ---- @param findstart integer +--- @param findstart 0|1 --- @param base string function M.omnifunc(findstart, base) if findstart == 1 then diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 99cc9bea09..8fb591bc46 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -231,7 +231,6 @@ function TSHighlighter:on_changedtree(changes) end --- Gets the query used for @param lang --- ---@package ---@param lang string Language used by the highlighter. ---@return vim.treesitter.highlighter.Query diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 79566f5eeb..d01da8be71 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -1,5 +1,3 @@ ---- @defgroup lua-treesitter-languagetree ---- --- @brief A \*LanguageTree\* contains a tree of parsers: the root treesitter parser for {lang} and --- any "injected" language parsers, which themselves may inject other languages, recursively. --- For example a Lua buffer containing some Vimscript commands needs multiple parsers to fully @@ -433,7 +431,7 @@ function LanguageTree:parse(range) local query_time = 0 local total_parse_time = 0 - --- At least 1 region is invalid + -- At least 1 region is invalid if not self:is_valid(true) then changes, no_regions_parsed, total_parse_time = self:_parse_regions(range) -- Need to run injections when we parsed something diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 5bb9e07a82..57272dbd60 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -231,7 +231,7 @@ end ---@param lang string Language to use for the query ---@param query_name string Name of the query (e.g. "highlights") --- ----@return vim.treesitter.Query|nil -- Parsed query. `nil` if no query files are found. +---@return vim.treesitter.Query|nil : Parsed query. `nil` if no query files are found. M.get = vim.func._memoize('concat-2', function(lang, query_name) if explicit_queries[lang][query_name] then return explicit_queries[lang][query_name] @@ -1019,6 +1019,8 @@ end --- vim.bo.omnifunc = 'v:lua.vim.treesitter.query.omnifunc' --- ``` --- +--- @param findstart 0|1 +--- @param base string function M.omnifunc(findstart, base) return vim.treesitter._query_linter.omnifunc(findstart, base) end diff --git a/runtime/lua/vim/uri.lua b/runtime/lua/vim/uri.lua index 038aa8acfb..7660dc42e7 100644 --- a/runtime/lua/vim/uri.lua +++ b/runtime/lua/vim/uri.lua @@ -1,4 +1,4 @@ ----TODO: This is implemented only for files currently. +-- TODO: This is implemented only for files currently. -- https://tools.ietf.org/html/rfc3986 -- https://tools.ietf.org/html/rfc2732 -- https://tools.ietf.org/html/rfc2396 @@ -116,7 +116,6 @@ end ---Gets the buffer for a uri. ---Creates a new unloaded buffer if no buffer for the uri already exists. --- ---@param uri string ---@return integer bufnr function M.uri_to_bufnr(uri) diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua index 58c2a2386d..09a6fa825b 100644 --- a/runtime/lua/vim/version.lua +++ b/runtime/lua/vim/version.lua @@ -1,6 +1,5 @@ ---- @defgroup vim.version ---- ---- @brief The \`vim.version\` module provides functions for comparing versions and ranges +--- @brief +--- The `vim.version` module provides functions for comparing versions and ranges --- conforming to the https://semver.org spec. Plugins, and plugin managers, can use this to check --- available tools and dependencies on the current system. --- @@ -13,9 +12,9 @@ --- end --- ``` --- ---- \*vim.version()\* returns the version of the current Nvim process. +--- *vim.version()* returns the version of the current Nvim process. --- ---- VERSION RANGE SPEC \*version-range\* +--- VERSION RANGE SPEC *version-range* --- --- A version "range spec" defines a semantic version range which can be tested against a version, --- using |vim.version.range()|. -- cgit From 3d96e3f9f25389e979bb7f2417ec2135f79fbfbb Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Mon, 26 Feb 2024 11:42:16 -0800 Subject: refactor(lsp): alias for CompletionResult --- runtime/lua/vim/lsp/_completion.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/_completion.lua b/runtime/lua/vim/lsp/_completion.lua index 84dbf9083e..3a38c1b5e1 100644 --- a/runtime/lua/vim/lsp/_completion.lua +++ b/runtime/lua/vim/lsp/_completion.lua @@ -4,6 +4,8 @@ local lsp = vim.lsp local protocol = lsp.protocol local ms = protocol.Methods +--- @alias vim.lsp.CompletionResult lsp.CompletionList | lsp.CompletionItem[] + ---@param input string unparsed snippet ---@return string parsed snippet local function parse_snippet(input) @@ -37,7 +39,7 @@ local function get_completion_word(item) return item.label end ----@param result lsp.CompletionList|lsp.CompletionItem[] +---@param result vim.lsp.CompletionResult ---@return lsp.CompletionItem[] local function get_items(result) if result.items then @@ -49,7 +51,7 @@ end --- Turns the result of a `textDocument/completion` request into vim-compatible --- |complete-items|. --- ----@param result lsp.CompletionList|lsp.CompletionItem[] Result of `textDocument/completion` +---@param result vim.lsp.CompletionResult Result of `textDocument/completion` ---@param prefix string prefix to filter the completion items ---@return table[] ---@see complete-items @@ -130,7 +132,7 @@ end ---@param lnum integer 0-indexed line number ---@param client_start_boundary integer 0-indexed word boundary ---@param server_start_boundary? integer 0-indexed word boundary, based on textEdit.range.start.character ----@param result lsp.CompletionList|lsp.CompletionItem[] +---@param result vim.lsp.CompletionResult ---@param encoding string ---@return table[] matches ---@return integer? server_start_boundary -- cgit From 63f9c2da9aab52fa698fcbfdbc58ffd41794d28a Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Mon, 26 Feb 2024 11:42:51 -0800 Subject: feat(lsp): support completion itemDefaults --- runtime/lua/vim/lsp/_completion.lua | 40 ++++++++++++++++++++++++++++++++++++- runtime/lua/vim/lsp/protocol.lua | 8 ++++++++ runtime/lua/vim/lsp/util.lua | 4 ++++ 3 files changed, 51 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/_completion.lua b/runtime/lua/vim/lsp/_completion.lua index 3a38c1b5e1..a169f96565 100644 --- a/runtime/lua/vim/lsp/_completion.lua +++ b/runtime/lua/vim/lsp/_completion.lua @@ -6,6 +6,14 @@ local ms = protocol.Methods --- @alias vim.lsp.CompletionResult lsp.CompletionList | lsp.CompletionItem[] +-- TODO(mariasolos): Remove this declaration once we figure out a better way to handle +-- literal/anonymous types (see https://github.com/neovim/neovim/pull/27542/files#r1495259331). +--- @class lsp.ItemDefaults +--- @field editRange lsp.Range | { insert: lsp.Range, replace: lsp.Range } | nil +--- @field insertTextFormat lsp.InsertTextFormat? +--- @field insertTextMode lsp.InsertTextMode? +--- @field data any + ---@param input string unparsed snippet ---@return string parsed snippet local function parse_snippet(input) @@ -39,13 +47,43 @@ local function get_completion_word(item) return item.label end +--- Applies the given defaults to the completion item, modifying it in place. +--- +--- @param item lsp.CompletionItem +--- @param defaults lsp.ItemDefaults? +local function apply_defaults(item, defaults) + if not defaults then + return + end + + item.insertTextFormat = item.insertTextFormat or defaults.insertTextFormat + item.insertTextMode = item.insertTextMode or defaults.insertTextMode + item.data = item.data or defaults.data + if defaults.editRange then + local textEdit = item.textEdit or {} + item.textEdit = textEdit + textEdit.newText = textEdit.newText or item.textEditText or item.insertText + if defaults.editRange.start then + textEdit.range = textEdit.range or defaults.editRange + elseif defaults.editRange.insert then + textEdit.insert = defaults.editRange.insert + textEdit.replace = defaults.editRange.replace + end + end +end + ---@param result vim.lsp.CompletionResult ---@return lsp.CompletionItem[] local function get_items(result) if result.items then + for _, item in ipairs(result.items) do + ---@diagnostic disable-next-line: param-type-mismatch + apply_defaults(item, result.itemDefaults) + end return result.items + else + return result end - return result end --- Turns the result of a `textDocument/completion` request into vim-compatible diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 82e8c4a7de..fb41311961 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -764,6 +764,14 @@ function protocol.make_client_capabilities() return res end)(), }, + completionList = { + itemDefaults = { + 'editRange', + 'insertTextFormat', + 'insertTextMode', + 'data', + }, + }, -- TODO(tjdevries): Implement this contextSupport = false, diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index e371cb0e15..3973e606f8 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -551,6 +551,10 @@ end --- Can be used to extract the completion items from a --- `textDocument/completion` request, which may return one of --- `CompletionItem[]`, `CompletionList` or null. +--- +--- Note that this method doesn't apply `itemDefaults` to `CompletionList`s, and hence the returned +--- results might be incorrect. +--- ---@deprecated ---@param result table The result of a `textDocument/completion` request ---@return lsp.CompletionItem[] List of completion items -- cgit From cb146cc4aad746053535533cbea8834414ea82a2 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Fri, 9 Feb 2024 10:35:13 -0800 Subject: docs(lpeg): merge upstream changes --- runtime/lua/vim/_meta/lpeg.lua | 70 +++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/lpeg.lua b/runtime/lua/vim/_meta/lpeg.lua index f2239e5e5a..fef07d3046 100644 --- a/runtime/lua/vim/_meta/lpeg.lua +++ b/runtime/lua/vim/_meta/lpeg.lua @@ -2,7 +2,7 @@ error('Cannot require a meta file') -- These types were taken from https://github.com/LuaCATS/lpeg --- (based on revision 4aded588f9531d89555566bb1de27490354b91c7) +-- (based on revision e6789e28e5b91a4a277a2a03081d708c403a3e34) -- with types being renamed to include the vim namespace and with some descriptions made less verbose. --- @brief
help
@@ -49,10 +49,10 @@ local Pattern = {}
 --- Example:
 ---
 --- ```lua
---- local pattern = lpeg.R("az") ^ 1 * -1
---- assert(pattern:match("hello") == 6)
---- assert(lpeg.match(pattern, "hello") == 6)
---- assert(pattern:match("1 hello") == nil)
+--- local pattern = lpeg.R('az') ^ 1 * -1
+--- assert(pattern:match('hello') == 6)
+--- assert(lpeg.match(pattern, 'hello') == 6)
+--- assert(pattern:match('1 hello') == nil)
 --- ```
 ---
 --- @param pattern vim.lpeg.Pattern
@@ -73,10 +73,10 @@ function vim.lpeg.match(pattern, subject, init) end
 --- Example:
 ---
 --- ```lua
---- local pattern = lpeg.R("az") ^ 1 * -1
---- assert(pattern:match("hello") == 6)
---- assert(lpeg.match(pattern, "hello") == 6)
---- assert(pattern:match("1 hello") == nil)
+--- local pattern = lpeg.R('az') ^ 1 * -1
+--- assert(pattern:match('hello') == 6)
+--- assert(lpeg.match(pattern, 'hello') == 6)
+--- assert(pattern:match('1 hello') == nil)
 --- ```
 ---
 --- @param subject string
@@ -103,7 +103,7 @@ function vim.lpeg.version() end
 --- @param max integer
 function vim.lpeg.setmaxstack(max) end
 
---- Converts the given value into a proper pattern. This following rules are applied:
+--- Converts the given value into a proper pattern. The following rules are applied:
 --- * If the argument is a pattern, it is returned unmodified.
 --- * If the argument is a string, it is translated to a pattern that matches the string literally.
 --- * If the argument is a non-negative number `n`, the result is a pattern that matches exactly `n` characters.
@@ -113,7 +113,7 @@ function vim.lpeg.setmaxstack(max) end
 --- * If the argument is a boolean, the result is a pattern that always succeeds or always fails
 --- (according to the boolean value), without consuming any input.
 --- * If the argument is a table, it is interpreted as a grammar (see Grammars).
---- * If the argument is a function, returns a pattern equivalent to a match-time captureover the empty string.
+--- * If the argument is a function, returns a pattern equivalent to a match-time capture over the empty string.
 ---
 --- @param value vim.lpeg.Pattern|string|integer|boolean|table|function
 --- @return vim.lpeg.Pattern
@@ -121,7 +121,7 @@ function vim.lpeg.P(value) end
 
 --- Returns a pattern that matches only if the input string at the current position is preceded by `patt`.
 --- Pattern `patt` must match only strings with some fixed length, and it cannot contain captures.
---- Like the and predicate, this pattern never consumes any input, independently of success or failure.
+--- Like the `and` predicate, this pattern never consumes any input, independently of success or failure.
 ---
 --- @param pattern vim.lpeg.Pattern
 --- @return vim.lpeg.Pattern
@@ -129,14 +129,14 @@ function vim.lpeg.B(pattern) end
 
 --- Returns a pattern that matches any single character belonging to one of the given ranges.
 --- Each `range` is a string `xy` of length 2, representing all characters with code between the codes of
---- `x` and `y` (both inclusive). As an example, the pattern `lpeg.R("09")` matches any digit, and
---- `lpeg.R("az", "AZ")` matches any ASCII letter.
+--- `x` and `y` (both inclusive). As an example, the pattern ``lpeg.R('09')`` matches any digit, and
+--- ``lpeg.R('az', 'AZ')`` matches any ASCII letter.
 ---
 --- Example:
 ---
 --- ```lua
---- local pattern = lpeg.R("az") ^ 1 * -1
---- assert(pattern:match("hello") == 6)
+--- local pattern = lpeg.R('az') ^ 1 * -1
+--- assert(pattern:match('hello') == 6)
 --- ```
 ---
 --- @param ... string
@@ -144,9 +144,9 @@ function vim.lpeg.B(pattern) end
 function vim.lpeg.R(...) end
 
 --- Returns a pattern that matches any single character that appears in the given string (the `S` stands for Set).
---- As an example, the pattern `lpeg.S("+-*/")` matches any arithmetic operator. Note that, if `s` is a character
+--- As an example, the pattern ``lpeg.S('+-*/')`` matches any arithmetic operator. Note that, if `s` is a character
 --- (that is, a string of length 1), then `lpeg.P(s)` is equivalent to `lpeg.S(s)` which is equivalent to
---- `lpeg.R(s..s)`. Note also that both `lpeg.S("")` and `lpeg.R()` are patterns that always fail.
+--- `lpeg.R(s..s)`. Note also that both ``lpeg.S('')`` and `lpeg.R()` are patterns that always fail.
 ---
 --- @param string string
 --- @return vim.lpeg.Pattern
@@ -158,7 +158,7 @@ function vim.lpeg.S(string) end
 --- Example:
 ---
 --- ```lua
---- local b = lpeg.P({"(" * ((1 - lpeg.S "()") + lpeg.V(1)) ^ 0 * ")"})
+--- local b = lpeg.P({'(' * ((1 - lpeg.S '()') + lpeg.V(1)) ^ 0 * ')'})
 --- assert(b:match('((string))') == 11)
 --- assert(b:match('(') == nil)
 --- ```
@@ -191,12 +191,12 @@ function vim.lpeg.V(v) end
 ---
 --- ```lua
 --- lpeg.locale(lpeg)
---- local space = lpeg.space^0
---- local name = lpeg.C(lpeg.alpha^1) * space
---- local sep = lpeg.S(",;") * space
---- local pair = lpeg.Cg(name * "=" * space * name) * sep^-1
---- local list = lpeg.Cf(lpeg.Ct("") * pair^0, rawset)
---- local t = list:match("a=b, c = hi; next = pi")
+--- local space = lpeg.space ^ 0
+--- local name = lpeg.C(lpeg.alpha ^ 1) * space
+--- local sep = lpeg.S(',;') * space
+--- local pair = lpeg.Cg(name * '=' * space * name) * sep ^ -1
+--- local list = lpeg.Cf(lpeg.Ct('') * pair ^ 0, rawset)
+--- local t = list:match('a=b, c = hi; next = pi')
 --- assert(t.a == 'b')
 --- assert(t.c == 'hi')
 --- assert(t.next == 'pi')
@@ -216,8 +216,8 @@ function vim.lpeg.locale(tab) end
 --- ```lua
 --- local function split (s, sep)
 ---   sep = lpeg.P(sep)
----   local elem = lpeg.C((1 - sep)^0)
----   local p = elem * (sep * elem)^0
+---   local elem = lpeg.C((1 - sep) ^ 0)
+---   local p = elem * (sep * elem) ^ 0
 ---   return lpeg.match(p, s)
 --- end
 --- local a, b, c = split('a,b,c', ',')
@@ -265,11 +265,11 @@ function vim.lpeg.Cc(...) end
 --- Example:
 ---
 --- ```lua
---- local number = lpeg.R("09") ^ 1 / tonumber
---- local list = number * ("," * number) ^ 0
+--- local number = lpeg.R('09') ^ 1 / tonumber
+--- local list = number * (',' * number) ^ 0
 --- local function add(acc, newvalue) return acc + newvalue end
 --- local sum = lpeg.Cf(list, add)
---- assert(sum:match("10,30,43") == 83)
+--- assert(sum:match('10,30,43') == 83)
 --- ```
 ---
 --- @param patt vim.lpeg.Pattern
@@ -294,7 +294,7 @@ function vim.lpeg.Cg(patt, name) end
 --- ```lua
 --- local I = lpeg.Cp()
 --- local function anywhere(p) return lpeg.P({I * p * I + 1 * lpeg.V(1)}) end
---- local match_start, match_end = anywhere("world"):match("hello world!")
+--- local match_start, match_end = anywhere('world'):match('hello world!')
 --- assert(match_start == 7)
 --- assert(match_end == 12)
 --- ```
@@ -313,7 +313,7 @@ function vim.lpeg.Cp() end
 --- ```lua
 --- local function gsub (s, patt, repl)
 ---   patt = lpeg.P(patt)
----   patt = lpeg.Cs((patt / repl + 1)^0)
+---   patt = lpeg.Cs((patt / repl + 1) ^ 0)
 ---   return lpeg.match(patt, s)
 --- end
 --- assert(gsub('Hello, xxx!', 'xxx', 'World') == 'Hello, World!')
@@ -337,9 +337,9 @@ function vim.lpeg.Ct(patt) end
 --- and then calls `function`. The given function gets as arguments the entire subject, the current position
 --- (after the match of `patt`), plus any capture values produced by `patt`. The first value returned by `function`
 --- defines how the match happens. If the call returns a number, the match succeeds and the returned number
---- becomes the new current position. (Assuming a subject sand current position i, the returned number must be
---- in the range [i, len(s) + 1].) If the call returns true, the match succeeds without consuming any input
---- (so, to return true is equivalent to return i). If the call returns false, nil, or no value, the match fails.
+--- becomes the new current position. (Assuming a subject sand current position `i`, the returned number must be
+--- in the range `[i, len(s) + 1]`.) If the call returns `true`, the match succeeds without consuming any input
+--- (so, to return true is equivalent to return `i`). If the call returns `false`, `nil`, or no value, the match fails.
 --- Any extra values returned by the function become the values produced by the capture.
 ---
 --- @param patt vim.lpeg.Pattern
-- 
cgit 


From 0190771713241b10872b9e2118e16ea4e4b2d1a0 Mon Sep 17 00:00:00 2001
From: Ilia Choly 
Date: Wed, 28 Feb 2024 04:50:53 -0500
Subject: fix(lua): remove uri fragment from file paths (#27647)

Problem: Some LSP servers return `textDocument/documentLink` responses
         containing file URIs with line/column numbers in the fragment.
         `vim.uri_to_fname` returns invalid file names for these URIs.

Solution: Remove the URI fragment from file URIs.
---
 runtime/lua/vim/uri.lua | 4 ++++
 1 file changed, 4 insertions(+)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/uri.lua b/runtime/lua/vim/uri.lua
index 7660dc42e7..b4e4098b91 100644
--- a/runtime/lua/vim/uri.lua
+++ b/runtime/lua/vim/uri.lua
@@ -104,6 +104,10 @@ function M.uri_to_fname(uri)
   if scheme ~= 'file' then
     return uri
   end
+  local fragment_index = uri:find('#')
+  if fragment_index ~= nil then
+    uri = uri:sub(1, fragment_index - 1)
+  end
   uri = M.uri_decode(uri)
   --TODO improve this.
   if is_windows_file_uri(uri) then
-- 
cgit 


From 7311958e1238559db7a0b1f490f15f618f51af06 Mon Sep 17 00:00:00 2001
From: Jaehwang Jung 
Date: Thu, 29 Feb 2024 01:32:25 +0900
Subject: fix(lsp): remove unnecessary file load/write when renaming (#27621)

Previously rename would unconditionally read the to-be-renamed file from the
disk and write it to the disk. This is redundant in some cases

If the file is not already loaded, it's not attached to lsp client, so nvim
doesn't need to care about this file.
If the file is loaded but has no change, it doesn't need to be written.
---
 runtime/lua/vim/lsp/util.lua | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 3973e606f8..d2a5d9a08e 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -710,11 +710,12 @@ function M.rename(old_fname, new_fname, opts)
   end
 
   for _, b in ipairs(oldbufs) do
-    vim.fn.bufload(b)
-    -- The there may be pending changes in the buffer
-    api.nvim_buf_call(b, function()
-      vim.cmd('w!')
-    end)
+    -- There may be pending changes in the buffer
+    if api.nvim_buf_is_loaded(b) then
+      api.nvim_buf_call(b, function()
+        vim.cmd('update!')
+      end)
+    end
   end
 
   local newdir = assert(vim.fs.dirname(new_fname))
-- 
cgit 


From aa62898ae329ec7ef978b4e7263c6f41b28f2503 Mon Sep 17 00:00:00 2001
From: notomo 
Date: Thu, 29 Feb 2024 01:36:28 +0900
Subject: fix(lsp): correct the error message's cmd on spawning (#27632)

---
 runtime/lua/vim/lsp/rpc.lua | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 1455ab51fa..e52c06a1bd 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -819,7 +819,8 @@ function M.start(cmd, dispatchers, extra_spawn_params)
     else
       sfx = string.format(' with error message: %s', err)
     end
-    local msg = string.format('Spawning language server with cmd: `%s` failed%s', cmd, sfx)
+    local msg =
+      string.format('Spawning language server with cmd: `%s` failed%s', vim.inspect(cmd), sfx)
     vim.notify(msg, vim.log.levels.WARN)
     return nil
   end
-- 
cgit 


From d981670bc9acd4cfd7b0768b8bc64390b026bf98 Mon Sep 17 00:00:00 2001
From: Maria José Solano 
Date: Sun, 25 Feb 2024 12:05:35 -0800
Subject: refactor(lsp): remove outdated comment

---
 runtime/lua/vim/lsp/protocol.lua | 18 ------------------
 1 file changed, 18 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index fb41311961..4a5ab1a73d 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -2,24 +2,6 @@
 
 -- Protocol for the Microsoft Language Server Protocol (mslsp)
 
---[=[
----@private
---- Useful for interfacing with:
---- https://github.com/microsoft/language-server-protocol/raw/gh-pages/_specifications/specification-3-14.md
-function transform_schema_comments()
-  nvim.command [[silent! '<,'>g/\/\*\*\|\*\/\|^$/d]]
-  nvim.command [[silent! '<,'>s/^\(\s*\) \* \=\(.*\)/\1--\2/]]
-end
----@private
-function transform_schema_to_table()
-  transform_schema_comments()
-  nvim.command [[silent! '<,'>s/: \S\+//]]
-  nvim.command [[silent! '<,'>s/export const //]]
-  nvim.command [[silent! '<,'>s/export namespace \(\S*\)\s*{/protocol.\1 = {/]]
-  nvim.command [[silent! '<,'>s/namespace \(\S*\)\s*{/protocol.\1 = {/]]
-end
---]=]
-
 local protocol = {
   --- @enum lsp.DiagnosticSeverity
   DiagnosticSeverity = {
-- 
cgit 


From 853f647da618d2891e4ac513fb96d3c8a42fa131 Mon Sep 17 00:00:00 2001
From: Maria José Solano 
Date: Sun, 25 Feb 2024 12:45:39 -0800
Subject: fix(lsp): handle reverse lookup in capabilities

---
 runtime/lua/vim/lsp/protocol.lua | 52 ++++++++++++----------------------------
 1 file changed, 15 insertions(+), 37 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index 4a5ab1a73d..fa614780c2 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -1,5 +1,11 @@
 --- @diagnostic disable: duplicate-doc-alias
 
+local function get_value_set(t)
+  return vim.iter.filter(function(i)
+    return type(i) == 'number'
+  end, ipairs(t))
+end
+
 -- Protocol for the Microsoft Language Server Protocol (mslsp)
 
 local protocol = {
@@ -295,6 +301,7 @@ local protocol = {
   },
 }
 
+-- TODO(mariasolos): Remove this reverse lookup.
 for k, v in pairs(protocol) do
   local tbl = vim.deepcopy(v, true)
   vim.tbl_add_reverse_lookup(tbl)
@@ -705,7 +712,10 @@ function protocol.make_client_capabilities()
         codeActionLiteralSupport = {
           codeActionKind = {
             valueSet = (function()
-              local res = vim.tbl_values(protocol.CodeActionKind)
+              local res = vim.iter.filter(function(value)
+                -- Filter out the keys that were added by the reverse lookup.
+                return value:match('^%l')
+              end, vim.tbl_values(protocol.CodeActionKind))
               table.sort(res)
               return res
             end)(),
@@ -736,15 +746,7 @@ function protocol.make_client_capabilities()
           documentationFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText },
         },
         completionItemKind = {
-          valueSet = (function()
-            local res = {}
-            for k in ipairs(protocol.CompletionItemKind) do
-              if type(k) == 'number' then
-                table.insert(res, k)
-              end
-            end
-            return res
-          end)(),
+          valueSet = get_value_set(protocol.CompletionItemKind),
         },
         completionList = {
           itemDefaults = {
@@ -794,15 +796,7 @@ function protocol.make_client_capabilities()
       documentSymbol = {
         dynamicRegistration = false,
         symbolKind = {
-          valueSet = (function()
-            local res = {}
-            for k in ipairs(protocol.SymbolKind) do
-              if type(k) == 'number' then
-                table.insert(res, k)
-              end
-            end
-            return res
-          end)(),
+          valueSet = get_value_set(protocol.SymbolKind),
         },
         hierarchicalDocumentSymbolSupport = true,
       },
@@ -813,15 +807,7 @@ function protocol.make_client_capabilities()
       publishDiagnostics = {
         relatedInformation = true,
         tagSupport = {
-          valueSet = (function()
-            local res = {}
-            for k in ipairs(protocol.DiagnosticTag) do
-              if type(k) == 'number' then
-                table.insert(res, k)
-              end
-            end
-            return res
-          end)(),
+          valueSet = get_value_set(protocol.DiagnosticTag),
         },
         dataSupport = true,
       },
@@ -833,15 +819,7 @@ function protocol.make_client_capabilities()
       symbol = {
         dynamicRegistration = false,
         symbolKind = {
-          valueSet = (function()
-            local res = {}
-            for k in ipairs(protocol.SymbolKind) do
-              if type(k) == 'number' then
-                table.insert(res, k)
-              end
-            end
-            return res
-          end)(),
+          valueSet = get_value_set(protocol.SymbolKind),
         },
       },
       configuration = true,
-- 
cgit 


From f912030d4ed0998b3de90bad9f1b416fffff49c9 Mon Sep 17 00:00:00 2001
From: Maria José Solano 
Date: Wed, 28 Feb 2024 14:14:49 -0800
Subject: docs(lpeg): remove double backticks from meta (#27659)

---
 runtime/lua/vim/_meta/lpeg.lua | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/_meta/lpeg.lua b/runtime/lua/vim/_meta/lpeg.lua
index fef07d3046..202c99f18c 100644
--- a/runtime/lua/vim/_meta/lpeg.lua
+++ b/runtime/lua/vim/_meta/lpeg.lua
@@ -129,8 +129,8 @@ function vim.lpeg.B(pattern) end
 
 --- Returns a pattern that matches any single character belonging to one of the given ranges.
 --- Each `range` is a string `xy` of length 2, representing all characters with code between the codes of
---- `x` and `y` (both inclusive). As an example, the pattern ``lpeg.R('09')`` matches any digit, and
---- ``lpeg.R('az', 'AZ')`` matches any ASCII letter.
+--- `x` and `y` (both inclusive). As an example, the pattern `lpeg.R('09')` matches any digit, and
+--- `lpeg.R('az', 'AZ')` matches any ASCII letter.
 ---
 --- Example:
 ---
@@ -144,9 +144,9 @@ function vim.lpeg.B(pattern) end
 function vim.lpeg.R(...) end
 
 --- Returns a pattern that matches any single character that appears in the given string (the `S` stands for Set).
---- As an example, the pattern ``lpeg.S('+-*/')`` matches any arithmetic operator. Note that, if `s` is a character
+--- As an example, the pattern `lpeg.S('+-*/')` matches any arithmetic operator. Note that, if `s` is a character
 --- (that is, a string of length 1), then `lpeg.P(s)` is equivalent to `lpeg.S(s)` which is equivalent to
---- `lpeg.R(s..s)`. Note also that both ``lpeg.S('')`` and `lpeg.R()` are patterns that always fail.
+--- `lpeg.R(s..s)`. Note also that both `lpeg.S('')` and `lpeg.R()` are patterns that always fail.
 ---
 --- @param string string
 --- @return vim.lpeg.Pattern
-- 
cgit 


From ce7c51a1a3b2b38cdba730aeb53840d0ace32173 Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Thu, 29 Feb 2024 07:19:26 +0800
Subject: vim-patch:9.1.0142: getregion() can be improved (#27662)

Problem:  getregion() can be improved (after v9.1.120)
Solution: change getregion() implementation to use pos as lists and
          one optional {opt} dictionary (Shougo Matsushita)

Note: The following is a breaking change!

Currently, the getregion() function (included as of patch v9.1.120) takes
3 arguments: the first 2 arguments are strings, describing a position,
arg3 is the type string.

However, that is slightly inflexible, there is no way to specify
additional arguments. So let's instead change the function signature to:

getregion(pos1, pos2 [, {Dict}]) where both pos1 and pos2 are lists.
This is slightly cleaner, and gives us the flexibility to specify
additional arguments as key/value pairs to the optional Dict arg.

Now it supports the "type" key to specify the selection type
(characterwise, blockwise or linewise) and now in addition one can also
define the selection type, independently of what the 'selection' option
actually is.

Technically, this is a breaking change, but since the getregion()
Vimscript function is still quite new, this should be fine.

closes: vim/vim#14090

https://github.com/vim/vim/commit/19b718828d8d5fab52d94c6cdba694641879ab38

Co-authored-by: Shougo Matsushita 
---
 runtime/lua/vim/_defaults.lua   |  3 ++-
 runtime/lua/vim/_meta/vimfn.lua | 42 ++++++++++++++++++++++++-----------------
 2 files changed, 27 insertions(+), 18 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua
index 7cece41ed3..c8131f8eb4 100644
--- a/runtime/lua/vim/_defaults.lua
+++ b/runtime/lua/vim/_defaults.lua
@@ -6,7 +6,8 @@ do
   do
     local function _visual_search(cmd)
       assert(cmd == '/' or cmd == '?')
-      local chunks = vim.fn.getregion('.', 'v', vim.fn.mode())
+      local chunks =
+        vim.fn.getregion(vim.fn.getpos('.'), vim.fn.getpos('v'), { type = vim.fn.mode() })
       local esc_chunks = vim
         .iter(chunks)
         :map(function(v)
diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua
index 779016f2d1..be89c7dd01 100644
--- a/runtime/lua/vim/_meta/vimfn.lua
+++ b/runtime/lua/vim/_meta/vimfn.lua
@@ -3525,13 +3525,24 @@ function vim.fn.getreg(regname, list) end
 --- @return table
 function vim.fn.getreginfo(regname) end
 
---- Returns the list of strings from {pos1} to {pos2} as if it's
---- selected in visual mode of {type}.
---- For possible values of {pos1} and {pos2} see |line()|.
---- {type} is the selection type:
----   "v" for |charwise| mode
----   "V" for |linewise| mode
----   "" for |blockwise-visual| mode
+--- Returns the list of strings from {pos1} to {pos2} in current
+--- buffer.
+---
+--- {pos1} and {pos2} must both be |List|s with four numbers.
+--- See |getpos()| for the format of the list.
+---
+--- The optional argument {opts} is a Dict and supports the
+--- following items:
+---
+---   type    Specify the selection type
+---       (default: "v"):
+---       "v"    for |charwise| mode
+---       "V"    for |linewise| mode
+---       ""  for |blockwise-visual| mode
+---
+---   exclusive  If |TRUE|, use exclusive selection
+---       for the end position 'selection'.
+---
 --- You can get the last selection type by |visualmode()|.
 --- If Visual mode is active, use |mode()| to get the Visual mode
 --- (e.g., in a |:vmap|).
@@ -3549,23 +3560,20 @@ function vim.fn.getreginfo(regname) end
 --- - If the selection starts or ends in the middle of a multibyte
 ---   character, it is not included but its selected part is
 ---   substituted with spaces.
---- - If {pos1} or {pos2} equals "v" (see |line()|) and it is not in
----   |visual-mode|, an empty list is returned.
---- - If {pos1}, {pos2} or {type} is an invalid string, an empty
----   list is returned.
---- - If {pos1} or {pos2} is a mark in different buffer, an empty
+--- - If {pos1} or {pos2} is not current in the buffer, an empty
 ---   list is returned.
 ---
 --- Examples: >
 ---   :xnoremap 
----   \ echom getregion('v', '.', mode())
+---   \ echom getregion(
+---   \ getpos('v'), getpos('.'), #{ type: mode() })
 --- <
 ---
---- @param pos1 string
---- @param pos2 string
---- @param type string
+--- @param pos1 table
+--- @param pos2 table
+--- @param opts? table
 --- @return string[]
-function vim.fn.getregion(pos1, pos2, type) end
+function vim.fn.getregion(pos1, pos2, opts) end
 
 --- The result is a String, which is type of register {regname}.
 --- The value will be one of:
-- 
cgit 


From f9e7c4c9c4fb89e6114a37387f3738d98cb4ba6a Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Thu, 29 Feb 2024 08:21:13 +0800
Subject: refactor(defaults): use getregion() for Visual mode gx (#27663)

Also make it work better on a multiline selection.
---
 runtime/lua/vim/_defaults.lua | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua
index c8131f8eb4..91baee1a1e 100644
--- a/runtime/lua/vim/_defaults.lua
+++ b/runtime/lua/vim/_defaults.lua
@@ -67,15 +67,6 @@ do
   )
   --- Map |gx| to call |vim.ui.open| on the identifier under the cursor
   do
-    -- TODO: use vim.region() when it lands... #13896 #16843
-    local function get_visual_selection()
-      local save_a = vim.fn.getreginfo('a')
-      vim.cmd([[norm! "ay]])
-      local selection = vim.fn.getreg('a', 1)
-      vim.fn.setreg('a', save_a)
-      return selection
-    end
-
     local function do_open(uri)
       local _, err = vim.ui.open(uri)
       if err then
@@ -89,7 +80,10 @@ do
       do_open(vim.fn.expand(''))
     end, { desc = gx_desc })
     vim.keymap.set({ 'x' }, 'gx', function()
-      do_open(get_visual_selection())
+      local lines =
+        vim.fn.getregion(vim.fn.getpos('.'), vim.fn.getpos('v'), { type = vim.fn.mode() })
+      -- Trim whitespace on each line and concatenate.
+      do_open(table.concat(vim.iter(lines):map(vim.trim):totable()))
     end, { desc = gx_desc })
   end
 end
-- 
cgit 


From 2c8f36a3b0b6e9d8a8c0d0f9cafff9cbf8bcb520 Mon Sep 17 00:00:00 2001
From: Christian Clason 
Date: Thu, 29 Feb 2024 10:21:02 +0100
Subject: fix(lsp): use plain loop for non-list-like table of protocol values

Fixup for #27628

Closes #27669
---
 runtime/lua/vim/lsp/protocol.lua | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index fa614780c2..7016209372 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -1,9 +1,17 @@
 --- @diagnostic disable: duplicate-doc-alias
 
+-- TODO(clason) can be simplified after reverse lookup is removed
+---@param t table
+---@return number[]
 local function get_value_set(t)
-  return vim.iter.filter(function(i)
-    return type(i) == 'number'
-  end, ipairs(t))
+  local result = {}
+  for _, v in pairs(t) do
+    if type(v) == 'number' then
+      table.insert(result, v)
+    end
+  end
+  table.sort(result)
+  return result
 end
 
 -- Protocol for the Microsoft Language Server Protocol (mslsp)
-- 
cgit 


From 6ab0876f51e8ff5debdff03b36508fe7279032b7 Mon Sep 17 00:00:00 2001
From: glepnir 
Date: Thu, 29 Feb 2024 19:39:11 +0800
Subject: docs(eval): getline and indent function support string type

Problem: getline and indent function missing string type in param.

Solution: add string type in eval gen.
---
 runtime/lua/vim/_meta/vimfn.lua | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua
index be89c7dd01..fa13c36a11 100644
--- a/runtime/lua/vim/_meta/vimfn.lua
+++ b/runtime/lua/vim/_meta/vimfn.lua
@@ -3185,7 +3185,7 @@ function vim.fn.getjumplist(winnr, tabnr) end
 --- 
Date: Sat, 2 Mar 2024 02:31:54 +0900
Subject: fix(lsp): rename undofile when renaming (#27684)

Problem:
After `rename()`, the undo information for the renamed file(s) are lost.

Solution:
Rename the undofile as well.
---
 runtime/lua/vim/lsp/util.lua | 7 +++++++
 1 file changed, 7 insertions(+)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index d2a5d9a08e..0553d39851 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -724,6 +724,13 @@ function M.rename(old_fname, new_fname, opts)
   local ok, err = os.rename(old_fname_full, new_fname)
   assert(ok, err)
 
+  local old_undofile = vim.fn.undofile(old_fname_full)
+  if uv.fs_stat(old_undofile) ~= nil then
+    local new_undofile = vim.fn.undofile(new_fname)
+    vim.fn.mkdir(assert(vim.fs.dirname(new_undofile)), 'p')
+    os.rename(old_undofile, new_undofile)
+  end
+
   if vim.fn.isdirectory(new_fname) == 0 then
     local newbuf = vim.fn.bufadd(new_fname)
     if win then
-- 
cgit 


From b87505e11656163ddf0dbbc16b7d224815873964 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Wed, 7 Feb 2024 11:24:44 +0000
Subject: refactor(watch): general tidy up

- Rename watch.poll to watch.watchdirs
- Unify how include and exclude is applied
- Improve type hints
---
 runtime/lua/vim/_watch.lua          | 202 +++++++++++++++++++-----------------
 runtime/lua/vim/lsp/_watchfiles.lua |   7 +-
 2 files changed, 111 insertions(+), 98 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/_watch.lua b/runtime/lua/vim/_watch.lua
index 092781826f..019af1822f 100644
--- a/runtime/lua/vim/_watch.lua
+++ b/runtime/lua/vim/_watch.lua
@@ -1,45 +1,61 @@
-local M = {}
 local uv = vim.uv
 
----@enum vim._watch.FileChangeType
-local FileChangeType = {
+local M = {}
+
+--- @enum vim._watch.FileChangeType
+--- Types of events watchers will emit.
+M.FileChangeType = {
   Created = 1,
   Changed = 2,
   Deleted = 3,
 }
 
---- Enumeration describing the types of events watchers will emit.
-M.FileChangeType = vim.tbl_add_reverse_lookup(FileChangeType)
-
---- Joins filepath elements by static '/' separator
+--- @class vim._watch.Opts
 ---
----@param ... (string) The path elements.
----@return string
-local function filepath_join(...)
-  return table.concat({ ... }, '/')
-end
-
---- Stops and closes a libuv |uv_fs_event_t| or |uv_fs_poll_t| handle
+--- @field debounce? integer ms
+---
+--- An |lpeg| pattern. Only changes to files whose full paths match the pattern
+--- will be reported. Only matches against non-directoriess, all directories will
+--- be watched for new potentially-matching files. exclude_pattern can be used to
+--- filter out directories. When nil, matches any file name.
+--- @field include_pattern? vim.lpeg.Pattern
 ---
----@param handle (uv.uv_fs_event_t|uv.uv_fs_poll_t) The handle to stop
-local function stop(handle)
-  local _, stop_err = handle:stop()
-  assert(not stop_err, stop_err)
-  local is_closing, close_err = handle:is_closing()
-  assert(not close_err, close_err)
-  if not is_closing then
-    handle:close()
+--- An |lpeg| pattern. Only changes to files and directories whose full path does
+--- not match the pattern will be reported. Matches against both files and
+--- directories. When nil, matches nothing.
+--- @field exclude_pattern? vim.lpeg.Pattern
+
+--- @alias vim._watch.Callback fun(path: string, change_type: vim._watch.FileChangeType)
+
+--- @class vim._watch.watch.Opts : vim._watch.Opts
+--- @field uvflags? uv.fs_event_start.flags
+
+--- @param path string
+--- @param opts? vim._watch.Opts
+local function skip(path, opts)
+  if not opts then
+    return false
+  end
+
+  if opts.include_pattern and opts.include_pattern:match(path) == nil then
+    return true
   end
+
+  if opts.exclude_pattern and opts.exclude_pattern:match(path) ~= nil then
+    return true
+  end
+
+  return false
 end
 
 --- Initializes and starts a |uv_fs_event_t|
 ---
----@param path (string) The path to watch
----@param opts (table|nil) Additional options
----     - uvflags (table|nil)
----                Same flags as accepted by |uv.fs_event_start()|
----@param callback (function) The function called when new events
----@return (function) Stops the watcher
+--- @param path string The path to watch
+--- @param opts vim._watch.watch.Opts? Additional options:
+---      - uvflags (table|nil)
+---                 Same flags as accepted by |uv.fs_event_start()|
+--- @param callback vim._watch.Callback Callback for new events
+--- @return fun() cancel Stops the watcher
 function M.watch(path, opts, callback)
   vim.validate({
     path = { path, 'string', false },
@@ -47,49 +63,69 @@ function M.watch(path, opts, callback)
     callback = { callback, 'function', false },
   })
 
+  opts = opts or {}
+
   path = vim.fs.normalize(path)
   local uvflags = opts and opts.uvflags or {}
-  local handle, new_err = vim.uv.new_fs_event()
-  assert(not new_err, new_err)
-  handle = assert(handle)
+  local handle = assert(uv.new_fs_event())
+
   local _, start_err = handle:start(path, uvflags, function(err, filename, events)
     assert(not err, err)
     local fullpath = path
     if filename then
-      filename = filename:gsub('\\', '/')
-      fullpath = filepath_join(fullpath, filename)
+      fullpath = vim.fs.normalize(vim.fs.joinpath(fullpath, filename))
     end
-    local change_type = events.change and M.FileChangeType.Changed or 0
+
+    if skip(fullpath, opts) then
+      return
+    end
+
+    --- @type vim._watch.FileChangeType
+    local change_type
     if events.rename then
-      local _, staterr, staterrname = vim.uv.fs_stat(fullpath)
+      local _, staterr, staterrname = uv.fs_stat(fullpath)
       if staterrname == 'ENOENT' then
         change_type = M.FileChangeType.Deleted
       else
         assert(not staterr, staterr)
         change_type = M.FileChangeType.Created
       end
+    elseif events.change then
+      change_type = M.FileChangeType.Changed
     end
     callback(fullpath, change_type)
   end)
+
   assert(not start_err, start_err)
+
   return function()
-    stop(handle)
+    local _, stop_err = handle:stop()
+    assert(not stop_err, stop_err)
+    local is_closing, close_err = handle:is_closing()
+    assert(not close_err, close_err)
+    if not is_closing then
+      handle:close()
+    end
   end
 end
 
---- @class watch.PollOpts
---- @field debounce? integer
---- @field include_pattern? vim.lpeg.Pattern
---- @field exclude_pattern? vim.lpeg.Pattern
+--- Initializes and starts a |uv_fs_event_t| recursively watching every directory underneath the
+--- directory at path.
+---
+--- @param path string The path to watch. Must refer to a directory.
+--- @param opts vim._watch.Opts? Additional options
+--- @param callback vim._watch.Callback Callback for new events
+--- @return fun() cancel Stops the watcher
+function M.watchdirs(path, opts, callback)
+  vim.validate({
+    path = { path, 'string', false },
+    opts = { opts, 'table', true },
+    callback = { callback, 'function', false },
+  })
 
----@param path string
----@param opts watch.PollOpts
----@param callback function Called on new events
----@return function cancel stops the watcher
-local function recurse_watch(path, opts, callback)
   opts = opts or {}
   local debounce = opts.debounce or 500
-  local uvflags = {}
+
   ---@type table handle by fullpath
   local handles = {}
 
@@ -98,28 +134,23 @@ local function recurse_watch(path, opts, callback)
   ---@type table[]
   local changesets = {}
 
-  local function is_included(filepath)
-    return opts.include_pattern and opts.include_pattern:match(filepath)
-  end
-  local function is_excluded(filepath)
-    return opts.exclude_pattern and opts.exclude_pattern:match(filepath)
-  end
-
-  local process_changes = function()
-    assert(false, "Replaced later. I'm only here as forward reference")
-  end
+  local process_changes --- @type fun()
 
+  --- @param filepath string
+  --- @return uv.fs_event_start.callback
   local function create_on_change(filepath)
     return function(err, filename, events)
       assert(not err, err)
       local fullpath = vim.fs.joinpath(filepath, filename)
-      if is_included(fullpath) and not is_excluded(filepath) then
-        table.insert(changesets, {
-          fullpath = fullpath,
-          events = events,
-        })
-        timer:start(debounce, 0, process_changes)
+      if skip(fullpath, opts) then
+        return
       end
+
+      table.insert(changesets, {
+        fullpath = fullpath,
+        events = events,
+      })
+      timer:start(debounce, 0, process_changes)
     end
   end
 
@@ -128,7 +159,7 @@ local function recurse_watch(path, opts, callback)
     local filechanges = vim.defaulttable()
     for i, change in ipairs(changesets) do
       changesets[i] = nil
-      if is_included(change.fullpath) and not is_excluded(change.fullpath) then
+      if not skip(change.fullpath) then
         table.insert(filechanges[change.fullpath], change.events)
       end
     end
@@ -137,10 +168,10 @@ local function recurse_watch(path, opts, callback)
         ---@type vim._watch.FileChangeType
         local change_type
         if stat then
-          change_type = FileChangeType.Created
+          change_type = M.FileChangeType.Created
           for _, event in ipairs(events_list) do
             if event.change then
-              change_type = FileChangeType.Changed
+              change_type = M.FileChangeType.Changed
             end
           end
           if stat.type == 'directory' then
@@ -148,10 +179,11 @@ local function recurse_watch(path, opts, callback)
             if not handle then
               handle = assert(uv.new_fs_event())
               handles[fullpath] = handle
-              handle:start(fullpath, uvflags, create_on_change(fullpath))
+              handle:start(fullpath, {}, create_on_change(fullpath))
             end
           end
         else
+          change_type = M.FileChangeType.Deleted
           local handle = handles[fullpath]
           if handle then
             if not handle:is_closing() then
@@ -159,15 +191,15 @@ local function recurse_watch(path, opts, callback)
             end
             handles[fullpath] = nil
           end
-          change_type = FileChangeType.Deleted
         end
         callback(fullpath, change_type)
       end)
     end
   end
+
   local root_handle = assert(uv.new_fs_event())
   handles[path] = root_handle
-  root_handle:start(path, uvflags, create_on_change(path))
+  root_handle:start(path, {}, create_on_change(path))
 
   --- "640K ought to be enough for anyone"
   --- Who has folders this deep?
@@ -175,12 +207,13 @@ local function recurse_watch(path, opts, callback)
 
   for name, type in vim.fs.dir(path, { depth = max_depth }) do
     local filepath = vim.fs.joinpath(path, name)
-    if type == 'directory' and not is_excluded(filepath) then
+    if type == 'directory' and not skip(filepath, opts) then
       local handle = assert(uv.new_fs_event())
       handles[filepath] = handle
-      handle:start(filepath, uvflags, create_on_change(filepath))
+      handle:start(filepath, {}, create_on_change(filepath))
     end
   end
+
   local function cancel()
     for fullpath, handle in pairs(handles) do
       if not handle:is_closing() then
@@ -191,34 +224,9 @@ local function recurse_watch(path, opts, callback)
     timer:stop()
     timer:close()
   end
-  return cancel
-end
 
---- Initializes and starts a |uv_fs_poll_t| recursively watching every file underneath the
---- directory at path.
----
----@param path (string) The path to watch. Must refer to a directory.
----@param opts (table|nil) Additional options
----     - debounce (number|nil)
----                Time events are debounced in ms. Defaults to 500
----     - include_pattern (LPeg pattern|nil)
----                An |lpeg| pattern. Only changes to files whose full paths match the pattern
----                will be reported. Only matches against non-directoriess, all directories will
----                be watched for new potentially-matching files. exclude_pattern can be used to
----                filter out directories. When nil, matches any file name.
----     - exclude_pattern (LPeg pattern|nil)
----                An |lpeg| pattern. Only changes to files and directories whose full path does
----                not match the pattern will be reported. Matches against both files and
----                directories. When nil, matches nothing.
----@param callback (function) The function called when new events
----@return function Stops the watcher
-function M.poll(path, opts, callback)
-  vim.validate({
-    path = { path, 'string', false },
-    opts = { opts, 'table', true },
-    callback = { callback, 'function', false },
-  })
-  return recurse_watch(path, opts, callback)
+  return cancel
 end
 
 return M
+
diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua
index 6ca60b78cd..220052be5f 100644
--- a/runtime/lua/vim/lsp/_watchfiles.lua
+++ b/runtime/lua/vim/lsp/_watchfiles.lua
@@ -7,7 +7,11 @@ local lpeg = vim.lpeg
 
 local M = {}
 
-M._watchfunc = (vim.fn.has('win32') == 1 or vim.fn.has('mac') == 1) and watch.watch or watch.poll
+if vim.fn.has('win32') == 1 or vim.fn.has('mac') == 1 then
+  M._watchfunc = watch.watch
+else
+  M._watchfunc = watch.watchdirs
+end
 
 ---@type table> client id -> registration id -> cancel function
 local cancels = vim.defaulttable()
@@ -164,3 +168,4 @@ function M.unregister(unreg, ctx)
 end
 
 return M
+
-- 
cgit 


From bf1e098d971d455cba1bdc9f6b2e777572fd6b16 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Wed, 7 Feb 2024 11:27:37 +0000
Subject: refactor(watch): simplify filechanges processing

---
 runtime/lua/vim/_watch.lua | 36 +++++++++++++++---------------------
 1 file changed, 15 insertions(+), 21 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/_watch.lua b/runtime/lua/vim/_watch.lua
index 019af1822f..03b632b53c 100644
--- a/runtime/lua/vim/_watch.lua
+++ b/runtime/lua/vim/_watch.lua
@@ -131,8 +131,10 @@ function M.watchdirs(path, opts, callback)
 
   local timer = assert(uv.new_timer())
 
-  ---@type table[]
-  local changesets = {}
+  --- Map of file path to boolean indicating if the file has been changed
+  --- at some point within the debounce cycle.
+  --- @type table
+  local filechanges = {}
 
   local process_changes --- @type fun()
 
@@ -146,34 +148,25 @@ function M.watchdirs(path, opts, callback)
         return
       end
 
-      table.insert(changesets, {
-        fullpath = fullpath,
-        events = events,
-      })
+      if not filechanges[fullpath] then
+        filechanges[fullpath] = events.change or false
+      end
       timer:start(debounce, 0, process_changes)
     end
   end
 
   process_changes = function()
-    ---@type table
-    local filechanges = vim.defaulttable()
-    for i, change in ipairs(changesets) do
-      changesets[i] = nil
-      if not skip(change.fullpath) then
-        table.insert(filechanges[change.fullpath], change.events)
-      end
-    end
-    for fullpath, events_list in pairs(filechanges) do
+    -- Since the callback is debounced it may have also been deleted later on
+    -- so we always need to check the existence of the file:
+    --   stat succeeds, changed=true  -> Changed
+    --   stat succeeds, changed=false -> Created
+    --   stat fails                   -> Removed
+    for fullpath, changed in pairs(filechanges) do
       uv.fs_stat(fullpath, function(_, stat)
         ---@type vim._watch.FileChangeType
         local change_type
         if stat then
-          change_type = M.FileChangeType.Created
-          for _, event in ipairs(events_list) do
-            if event.change then
-              change_type = M.FileChangeType.Changed
-            end
-          end
+          change_type = changed and M.FileChangeType.Changed or M.FileChangeType.Created
           if stat.type == 'directory' then
             local handle = handles[fullpath]
             if not handle then
@@ -195,6 +188,7 @@ function M.watchdirs(path, opts, callback)
         callback(fullpath, change_type)
       end)
     end
+    filechanges = {}
   end
 
   local root_handle = assert(uv.new_fs_event())
-- 
cgit 


From 816b56f878f0291c00a9018d5057b7b2b00f1891 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Wed, 7 Feb 2024 13:05:33 +0000
Subject: fix(lsp): cancel watchers when closing a client

---
 runtime/lua/vim/lsp/_watchfiles.lua | 9 +++++++++
 runtime/lua/vim/lsp/client.lua      | 1 +
 2 files changed, 10 insertions(+)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua
index 220052be5f..c66a76feae 100644
--- a/runtime/lua/vim/lsp/_watchfiles.lua
+++ b/runtime/lua/vim/lsp/_watchfiles.lua
@@ -167,5 +167,14 @@ function M.unregister(unreg, ctx)
   end
 end
 
+--- @param client_id integer
+function M.cancel(client_id)
+  for _, reg_cancels in pairs(cancels[client_id]) do
+    for _, cancel in pairs(reg_cancels) do
+      cancel()
+    end
+  end
+end
+
 return M
 
diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua
index c1b41a7183..1e709a1992 100644
--- a/runtime/lua/vim/lsp/client.lua
+++ b/runtime/lua/vim/lsp/client.lua
@@ -727,6 +727,7 @@ function Client:_stop(force)
       rpc.terminate()
       self._graceful_shutdown_failed = true
     end
+    vim.lsp._watchfiles.cancel(self.id)
   end)
 end
 
-- 
cgit 


From 1fe65b3457d2e0632831445899d6d8a4bff9daee Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Sat, 2 Mar 2024 06:42:39 +0800
Subject: vim-patch:87410ab3f556 (#27696)

runtime(doc): some improvements to getregion() docs (vim/vim#14122)

- Mention the default selection behavior
- Remove useless sentence
- Correct description about space padding

https://github.com/vim/vim/commit/87410ab3f556121dfb3b30515f40c5f079edd004
---
 runtime/lua/vim/_meta/vimfn.lua | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua
index fa13c36a11..ff95edddf6 100644
--- a/runtime/lua/vim/_meta/vimfn.lua
+++ b/runtime/lua/vim/_meta/vimfn.lua
@@ -3534,32 +3534,31 @@ function vim.fn.getreginfo(regname) end
 --- The optional argument {opts} is a Dict and supports the
 --- following items:
 ---
----   type    Specify the selection type
+---   type    Specify the region's selection type
 ---       (default: "v"):
 ---       "v"    for |charwise| mode
 ---       "V"    for |linewise| mode
 ---       ""  for |blockwise-visual| mode
 ---
 ---   exclusive  If |TRUE|, use exclusive selection
----       for the end position 'selection'.
+---       for the end position
+---       (default: follow 'selection')
 ---
 --- You can get the last selection type by |visualmode()|.
 --- If Visual mode is active, use |mode()| to get the Visual mode
 --- (e.g., in a |:vmap|).
---- This function uses the line and column number from the
---- specified position.
---- It is useful to get text starting and ending in different
---- columns, such as |charwise-visual| selection.
+--- This function is useful to get text starting and ending in
+--- different columns, such as a |charwise-visual| selection.
 ---
 --- Note that:
 --- - Order of {pos1} and {pos2} doesn't matter, it will always
 ---   return content from the upper left position to the lower
 ---   right position.
---- - If 'virtualedit' is enabled and selection is past the end of
----   line, resulting lines are filled with blanks.
---- - If the selection starts or ends in the middle of a multibyte
----   character, it is not included but its selected part is
----   substituted with spaces.
+--- - If 'virtualedit' is enabled and the region is past the end
+---   of the lines, resulting lines are padded with spaces.
+--- - If the region is blockwise and it starts or ends in the
+---   middle of a multi-cell character, it is not included but
+---   its selected part is substituted with spaces.
 --- - If {pos1} or {pos2} is not current in the buffer, an empty
 ---   list is returned.
 ---
-- 
cgit 


From 813dd36b72979dfd05479eb6402b9becc0faea29 Mon Sep 17 00:00:00 2001
From: Will Hopkins 
Date: Fri, 1 Mar 2024 14:59:32 -0800
Subject: fix(types): rename win_get_config return type to win_config

Follow-up to #27397
---
 runtime/lua/vim/_meta/api.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua
index d2f624fd97..94eab72291 100644
--- a/runtime/lua/vim/_meta/api.lua
+++ b/runtime/lua/vim/_meta/api.lua
@@ -2118,7 +2118,7 @@ function vim.api.nvim_win_get_buf(window) end
 --- `relative` is empty for normal windows.
 ---
 --- @param window integer Window handle, or 0 for current window
---- @return vim.api.keyset.float_config
+--- @return vim.api.keyset.win_config
 function vim.api.nvim_win_get_config(window) end
 
 --- Gets the (1,0)-indexed, buffer-relative cursor position for a given window
-- 
cgit 


From 4ff3217bbd8747d2d44680a825ac29097faf9c4b Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Wed, 7 Feb 2024 11:28:35 +0000
Subject: feat(lsp): add fswatch watchfunc backend

Problem:
  vim._watch.watchdirs has terrible performance.

Solution:
  - On linux use fswatch as a watcher backend if available.

  - Add File watcher section to health:vim.lsp. Warn if watchfunc is
    libuv-poll.
---
 runtime/lua/vim/_watch.lua          | 78 ++++++++++++++++++++++++++++++++++++-
 runtime/lua/vim/lsp/_watchfiles.lua |  3 +-
 runtime/lua/vim/lsp/health.lua      | 40 ++++++++++++++++---
 3 files changed, 114 insertions(+), 7 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/_watch.lua b/runtime/lua/vim/_watch.lua
index 03b632b53c..d199cf8e29 100644
--- a/runtime/lua/vim/_watch.lua
+++ b/runtime/lua/vim/_watch.lua
@@ -222,5 +222,81 @@ function M.watchdirs(path, opts, callback)
   return cancel
 end
 
-return M
+--- @param data string
+--- @param opts vim._watch.Opts?
+--- @param callback vim._watch.Callback
+local function fswatch_output_handler(data, opts, callback)
+  local d = vim.split(data, '%s+')
+
+  -- only consider the last reported event
+  local fullpath, event = d[1], d[#d]
+
+  if skip(fullpath, opts) then
+    return
+  end
+
+  --- @type integer
+  local change_type
+
+  if event == 'Created' then
+    change_type = M.FileChangeType.Created
+  elseif event == 'Removed' then
+    change_type = M.FileChangeType.Deleted
+  elseif event == 'Updated' then
+    change_type = M.FileChangeType.Changed
+  elseif event == 'Renamed' then
+    local _, staterr, staterrname = uv.fs_stat(fullpath)
+    if staterrname == 'ENOENT' then
+      change_type = M.FileChangeType.Deleted
+    else
+      assert(not staterr, staterr)
+      change_type = M.FileChangeType.Created
+    end
+  end
+
+  if change_type then
+    callback(fullpath, change_type)
+  end
+end
+
+--- @param path string The path to watch. Must refer to a directory.
+--- @param opts vim._watch.Opts?
+--- @param callback vim._watch.Callback Callback for new events
+--- @return fun() cancel Stops the watcher
+function M.fswatch(path, opts, callback)
+  -- debounce isn't the same as latency but close enough
+  local latency = 0.5 -- seconds
+  if opts and opts.debounce then
+    latency = opts.debounce / 1000
+  end
 
+  local obj = vim.system({
+    'fswatch',
+    '--event=Created',
+    '--event=Removed',
+    '--event=Updated',
+    '--event=Renamed',
+    '--event-flags',
+    '--recursive',
+    '--latency=' .. tostring(latency),
+    '--exclude',
+    '/.git/',
+    path,
+  }, {
+    stdout = function(err, data)
+      if err then
+        error(err)
+      end
+
+      for line in vim.gsplit(data or '', '\n', { plain = true, trimempty = true }) do
+        fswatch_output_handler(line, opts, callback)
+      end
+    end,
+  })
+
+  return function()
+    obj:kill(2)
+  end
+end
+
+return M
diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua
index c66a76feae..49328fbe9b 100644
--- a/runtime/lua/vim/lsp/_watchfiles.lua
+++ b/runtime/lua/vim/lsp/_watchfiles.lua
@@ -9,6 +9,8 @@ local M = {}
 
 if vim.fn.has('win32') == 1 or vim.fn.has('mac') == 1 then
   M._watchfunc = watch.watch
+elseif vim.fn.executable('fswatch') == 1 then
+  M._watchfunc = watch.fswatch
 else
   M._watchfunc = watch.watchdirs
 end
@@ -177,4 +179,3 @@ function M.cancel(client_id)
 end
 
 return M
-
diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua
index 15e4555b55..797a1097f9 100644
--- a/runtime/lua/vim/lsp/health.lua
+++ b/runtime/lua/vim/lsp/health.lua
@@ -1,10 +1,9 @@
 local M = {}
 
---- Performs a healthcheck for LSP
-function M.check()
-  local report_info = vim.health.info
-  local report_warn = vim.health.warn
+local report_info = vim.health.info
+local report_warn = vim.health.warn
 
+local function check_log()
   local log = vim.lsp.log
   local current_log_level = log.get_level()
   local log_level_string = log.levels[current_log_level] ---@type string
@@ -27,9 +26,11 @@ function M.check()
 
   local report_fn = (log_size / 1000000 > 100 and report_warn or report_info)
   report_fn(string.format('Log size: %d KB', log_size / 1000))
+end
 
-  local clients = vim.lsp.get_clients()
+local function check_active_clients()
   vim.health.start('vim.lsp: Active Clients')
+  local clients = vim.lsp.get_clients()
   if next(clients) then
     for _, client in pairs(clients) do
       local attached_to = table.concat(vim.tbl_keys(client.attached_buffers or {}), ',')
@@ -48,4 +49,33 @@ function M.check()
   end
 end
 
+local function check_watcher()
+  vim.health.start('vim.lsp: File watcher')
+  local watchfunc = vim.lsp._watchfiles._watchfunc
+  assert(watchfunc)
+  local watchfunc_name --- @type string
+  if watchfunc == vim._watch.watch then
+    watchfunc_name = 'libuv-watch'
+  elseif watchfunc == vim._watch.watchdirs then
+    watchfunc_name = 'libuv-watchdirs'
+  elseif watchfunc == vim._watch.fswatch then
+    watchfunc_name = 'fswatch'
+  else
+    local nm = debug.getinfo(watchfunc, 'S').source
+    watchfunc_name = string.format('Custom (%s)', nm)
+  end
+
+  report_info('File watch backend: ' .. watchfunc_name)
+  if watchfunc_name == 'libuv-watchdirs' then
+    report_warn('libuv-watchdirs has known performance issues. Consider installing fswatch.')
+  end
+end
+
+--- Performs a healthcheck for LSP
+function M.check()
+  check_log()
+  check_active_clients()
+  check_watcher()
+end
+
 return M
-- 
cgit 


From a5fe8f59d98398d04bed8586cee73864bbcdde92 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Tue, 27 Feb 2024 15:20:32 +0000
Subject: docs: improve/add documentation of Lua types

- Added `@inlinedoc` so single use Lua types can be inlined into the
  functions docs. E.g.

  ```lua
  --- @class myopts
  --- @inlinedoc
  ---
  --- Documentation for some field
  --- @field somefield integer

  --- @param opts myOpts
  function foo(opts)
  end
  ```

  Will be rendered as

  ```
  foo(opts)

    Parameters:
      - {opts} (table) Object with the fields:
               - somefield (integer) Documentation
                 for some field
  ```

- Marked many classes with with `@nodoc` or `(private)`.
  We can eventually introduce these when we want to.
---
 runtime/lua/vim/_editor.lua                  |   5 +-
 runtime/lua/vim/_inspector.lua               |  28 ++-
 runtime/lua/vim/_meta/builtin.lua            |   1 +
 runtime/lua/vim/_meta/lpeg.lua               |   2 +
 runtime/lua/vim/_meta/regex.lua              |   1 +
 runtime/lua/vim/_options.lua                 |   1 +
 runtime/lua/vim/diagnostic.lua               | 123 ++++++++---
 runtime/lua/vim/filetype.lua                 |  32 +--
 runtime/lua/vim/fs.lua                       |  49 +++--
 runtime/lua/vim/iter.lua                     |   3 +
 runtime/lua/vim/loader.lua                   |  72 ++++---
 runtime/lua/vim/lsp.lua                      | 297 +++++----------------------
 runtime/lua/vim/lsp/_changetracking.lua      |  12 +-
 runtime/lua/vim/lsp/buf.lua                  | 251 ++++++++++++----------
 runtime/lua/vim/lsp/client.lua               | 123 +++++++++--
 runtime/lua/vim/lsp/codelens.lua             |   6 +-
 runtime/lua/vim/lsp/diagnostic.lua           |   2 +-
 runtime/lua/vim/lsp/handlers.lua             |   1 +
 runtime/lua/vim/lsp/inlay_hint.lua           |  24 +--
 runtime/lua/vim/lsp/rpc.lua                  |  40 ++--
 runtime/lua/vim/lsp/semantic_tokens.lua      |  26 ++-
 runtime/lua/vim/lsp/util.lua                 |  91 +++++---
 runtime/lua/vim/secure.lua                   |  25 ++-
 runtime/lua/vim/shared.lua                   |  24 ++-
 runtime/lua/vim/snippet.lua                  |   4 +-
 runtime/lua/vim/treesitter.lua               |  30 +--
 runtime/lua/vim/treesitter/_query_linter.lua |   6 +-
 runtime/lua/vim/treesitter/dev.lua           |  69 ++++---
 runtime/lua/vim/treesitter/highlighter.lua   |  19 +-
 runtime/lua/vim/treesitter/language.lua      |  20 +-
 runtime/lua/vim/treesitter/languagetree.lua  |  41 ++--
 runtime/lua/vim/treesitter/query.lua         |  52 +++--
 runtime/lua/vim/version.lua                  |  61 +++---
 33 files changed, 810 insertions(+), 731 deletions(-)

(limited to 'runtime/lua/vim')

diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index 4e39abb2be..d14007312e 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -190,6 +190,7 @@ function vim._os_proc_children(ppid)
   return children
 end
 
+--- @nodoc
 --- @class vim.inspect.Opts
 --- @field depth? integer
 --- @field newline? string
@@ -454,7 +455,7 @@ vim.cmd = setmetatable({}, {
   end,
 })
 
---- @class vim.var_accessor
+--- @class (private) vim.var_accessor
 --- @field [string] any
 --- @field [integer] vim.var_accessor
 
@@ -1048,7 +1049,7 @@ function vim.deprecate(name, alternative, version, plugin, backtrace)
   -- e.g., when planned to be removed in version = '0.12' (soft-deprecated since 0.10-dev),
   -- show warnings since 0.11, including 0.11-dev (hard_deprecated_since = 0.11-dev).
   if plugin == 'Nvim' then
-    local current_version = vim.version() ---@type Version
+    local current_version = vim.version() ---@type vim.Version
     local removal_version = assert(vim.version.parse(version))
     local is_hard_deprecated ---@type boolean
 
diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua
index 9a073c32c4..a19d40c50d 100644
--- a/runtime/lua/vim/_inspector.lua
+++ b/runtime/lua/vim/_inspector.lua
@@ -1,8 +1,18 @@
----@class InspectorFilter
----@field syntax boolean include syntax based highlight groups (defaults to true)
----@field treesitter boolean include treesitter based highlight groups (defaults to true)
----@field extmarks boolean|"all" include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true)
----@field semantic_tokens boolean include semantic token highlights (defaults to true)
+--- @class vim._inspector.Filter
+--- @inlinedoc
+---
+--- Include syntax based highlight groups (defaults to true)
+--- @field syntax boolean
+---
+--- Include treesitter based highlight groups (defaults to true)
+--- @field treesitter boolean
+---
+--- Include extmarks. When `all`, then extmarks without a `hl_group` will also be included.
+--- (default: true)
+--- @field extmarks boolean|"all"
+---
+--- Include semantic token highlights (defaults to true)
+--- @field semantic_tokens boolean
 local defaults = {
   syntax = true,
   treesitter = true,
@@ -17,11 +27,7 @@ local defaults = {
 ---@param bufnr? integer defaults to the current buffer
 ---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor
 ---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor
----@param filter? InspectorFilter (table) a table with key-value pairs to filter the items
----               - syntax (boolean): include syntax based highlight groups (defaults to true)
----               - treesitter (boolean): include treesitter based highlight groups (defaults to true)
----               - extmarks (boolean|"all"): include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true)
----               - semantic_tokens (boolean): include semantic tokens (defaults to true)
+---@param filter? vim._inspector.Filter Table with key-value pairs to filter the items
 ---@return {treesitter:table,syntax:table,extmarks:table,semantic_tokens:table,buffer:integer,col:integer,row:integer} (table) a table with the following key-value pairs. Items are in "traversal order":
 ---               - treesitter: a list of treesitter captures
 ---               - syntax: a list of syntax groups
@@ -139,7 +145,7 @@ end
 ---@param bufnr? integer defaults to the current buffer
 ---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor
 ---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor
----@param filter? InspectorFilter (table) see |vim.inspect_pos()|
+---@param filter? vim._inspector.Filter (table) see |vim.inspect_pos()|
 function vim.show_pos(bufnr, row, col, filter)
   local items = vim.inspect_pos(bufnr, row, col, filter)
 
diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua
index 472162ecc1..4831989e1a 100644
--- a/runtime/lua/vim/_meta/builtin.lua
+++ b/runtime/lua/vim/_meta/builtin.lua
@@ -61,6 +61,7 @@ error('Cannot require a meta file')
 ---
 --- 
+---@nodoc ---@class vim.NIL ---@type vim.NIL diff --git a/runtime/lua/vim/_meta/lpeg.lua b/runtime/lua/vim/_meta/lpeg.lua index 202c99f18c..1ce40f3340 100644 --- a/runtime/lua/vim/_meta/lpeg.lua +++ b/runtime/lua/vim/_meta/lpeg.lua @@ -21,6 +21,7 @@ error('Cannot require a meta file') vim.lpeg = {} +--- @nodoc --- @class vim.lpeg.Pattern --- @operator unm: vim.lpeg.Pattern --- @operator add(vim.lpeg.Pattern): vim.lpeg.Pattern @@ -167,6 +168,7 @@ function vim.lpeg.S(string) end --- @return vim.lpeg.Pattern function vim.lpeg.V(v) end +--- @nodoc --- @class vim.lpeg.Locale --- @field alnum userdata --- @field alpha userdata diff --git a/runtime/lua/vim/_meta/regex.lua b/runtime/lua/vim/_meta/regex.lua index ab403b97e7..595ad96319 100644 --- a/runtime/lua/vim/_meta/regex.lua +++ b/runtime/lua/vim/_meta/regex.lua @@ -12,6 +12,7 @@ --- @return vim.regex function vim.regex(re) end +--- @nodoc --- @class vim.regex local regex = {} -- luacheck: no unused diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua index f1fed50c6d..bde9421552 100644 --- a/runtime/lua/vim/_options.lua +++ b/runtime/lua/vim/_options.lua @@ -797,6 +797,7 @@ end --- `vim.opt_global`. --- +--- @nodoc --- @class vim.Option local Option = {} -- luacheck: no unused diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 49165c4db9..3979e5512c 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -2,18 +2,44 @@ local api, if_nil = vim.api, vim.F.if_nil local M = {} +--- *diagnostic-structure* +--- +--- Diagnostics use the same indexing as the rest of the Nvim API (i.e. 0-based +--- rows and columns). |api-indexing| --- @class vim.Diagnostic +--- +--- Buffer number --- @field bufnr? integer ---- @field lnum integer 0-indexed ---- @field end_lnum? integer 0-indexed ---- @field col integer 0-indexed ---- @field end_col? integer 0-indexed +--- +--- The starting line of the diagnostic (0-indexed) +--- @field lnum integer +--- +--- The final line of the diagnostic (0-indexed) +--- @field end_lnum? integer +--- +--- The starting column of the diagnostic (0-indexed) +--- @field col integer +--- +--- The final column of the diagnostic (0-indexed) +--- @field end_col? integer +--- +--- The severity of the diagnostic |vim.diagnostic.severity| --- @field severity? vim.diagnostic.Severity +--- +--- The diagnostic text --- @field message string +--- +--- The source of the diagnostic --- @field source? string +--- +--- The diagnostic code --- @field code? string|integer +--- --- @field _tags? { deprecated: boolean, unnecessary: boolean} +--- +--- Arbitrary data plugins or users can add --- @field user_data? any arbitrary data plugins can add +--- --- @field namespace? integer --- @class vim.diagnostic.Opts @@ -104,7 +130,7 @@ local global_diagnostic_options = { severity_sort = false, } ---- @class vim.diagnostic.Handler +--- @class (private) vim.diagnostic.Handler --- @field show? fun(namespace: integer, bufnr: integer, diagnostics: vim.Diagnostic[], opts?: vim.diagnostic.OptsResolved) --- @field hide? fun(namespace:integer, bufnr:integer) @@ -154,7 +180,7 @@ do }) end ---- @class vim.diagnostic._extmark +--- @class (private) vim.diagnostic._extmark --- @field [1] integer id --- @field [2] integer start --- @field [3] integer end @@ -1018,31 +1044,52 @@ function M.get_next_pos(opts) return { next.lnum, next.col } end +--- A table with the following keys: --- @class vim.diagnostic.GetOpts +--- @inlinedoc +--- +--- Limit diagnostics to the given namespace. --- @field namespace? integer +--- +--- Limit diagnostics to the given line number. --- @field lnum? integer +--- +--- See |diagnostic-severity|. --- @field severity? vim.diagnostic.SeverityFilter +--- Configuration table with the following keys: --- @class vim.diagnostic.GotoOpts : vim.diagnostic.GetOpts +--- @inlinedoc +--- +--- Only consider diagnostics from the given namespace. +--- @field namespace integer +--- +--- Cursor position as a (row, col) tuple. +--- See |nvim_win_get_cursor()|. Defaults to the current cursor position. --- @field cursor_position? {[1]:integer,[2]:integer} +--- +--- Whether to loop around file or not. Similar to 'wrapscan'. +--- (default: `true`) --- @field wrap? boolean +--- +--- See |diagnostic-severity|. +--- @field severity vim.diagnostic.Severity +--- +--- If "true", call |vim.diagnostic.open_float()| +--- after moving. If a table, pass the table as the {opts} parameter +--- to |vim.diagnostic.open_float()|. Unless overridden, the float will show +--- diagnostics at the new cursor position (as if "cursor" were passed to +--- the "scope" option). +--- (default: `true`) --- @field float? boolean|vim.diagnostic.Opts.Float +--- +--- Window ID +--- (default: `0`) --- @field win_id? integer --- Move to the next diagnostic. --- ----@param opts? vim.diagnostic.GotoOpts (table) Configuration table with the following keys: ---- - namespace: (integer) Only consider diagnostics from the given namespace. ---- - cursor_position: (cursor position) Cursor position as a (row, col) tuple. ---- See |nvim_win_get_cursor()|. Defaults to the current cursor position. ---- - wrap: (boolean, default true) Whether to loop around file or not. Similar to 'wrapscan'. ---- - severity: See |diagnostic-severity|. ---- - float: (boolean or table, default true) If "true", call |vim.diagnostic.open_float()| ---- after moving. If a table, pass the table as the {opts} parameter ---- to |vim.diagnostic.open_float()|. Unless overridden, the float will show ---- diagnostics at the new cursor position (as if "cursor" were passed to ---- the "scope" option). ---- - win_id: (number, default 0) Window ID +---@param opts? vim.diagnostic.GotoOpts function M.goto_next(opts) diagnostic_move_pos(opts, M.get_next_pos(opts)) end @@ -1789,38 +1836,54 @@ function M.reset(namespace, bufnr) end end +--- Configuration table with the following keys: --- @class vim.diagnostic.setqflist.Opts +--- @inlinedoc +--- +--- Only add diagnostics from the given namespace. --- @field namespace? integer +--- +--- Open quickfix list after setting. +--- (default: `true`) --- @field open? boolean +--- +--- Title of quickfix list. Defaults to "Diagnostics". --- @field title? string +--- +--- See |diagnostic-severity|. --- @field severity? vim.diagnostic.Severity --- Add all diagnostics to the quickfix list. --- ----@param opts? vim.diagnostic.setqflist.Opts (table) Configuration table with the following keys: ---- - namespace: (number) Only add diagnostics from the given namespace. ---- - open: (boolean, default true) Open quickfix list after setting. ---- - title: (string) Title of quickfix list. Defaults to "Diagnostics". ---- - severity: See |diagnostic-severity|. +---@param opts? vim.diagnostic.setqflist.Opts function M.setqflist(opts) set_list(false, opts) end +---Configuration table with the following keys: --- @class vim.diagnostic.setloclist.Opts +--- @inlinedoc +--- +--- Only add diagnostics from the given namespace. --- @field namespace? integer +--- +--- Window number to set location list for. +--- (default: `0`) +--- @field winnr? integer +--- +--- Open the location list after setting. +--- (default: `true`) --- @field open? boolean +--- +--- Title of the location list. Defaults to "Diagnostics". --- @field title? string +--- +--- See |diagnostic-severity|. --- @field severity? vim.diagnostic.Severity ---- @field winnr? integer --- Add buffer diagnostics to the location list. --- ----@param opts? vim.diagnostic.setloclist.Opts (table) Configuration table with the following keys: ---- - namespace: (number) Only add diagnostics from the given namespace. ---- - winnr: (number, default 0) Window number to set location list for. ---- - open: (boolean, default true) Open the location list after setting. ---- - title: (string) Title of the location list. Defaults to "Diagnostics". ---- - severity: See |diagnostic-severity|. +---@param opts? vim.diagnostic.setloclist.Opts function M.setloclist(opts) set_list(true, opts) end diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index e7971d8916..fba76f93b2 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -2082,6 +2082,7 @@ local function normalize_path(path, as_pattern) end --- @class vim.filetype.add.filetypes +--- @inlinedoc --- @field pattern? vim.filetype.mapping --- @field extension? vim.filetype.mapping --- @field filename? vim.filetype.mapping @@ -2170,7 +2171,7 @@ end --- } --- ``` --- ----@param filetypes vim.filetype.add.filetypes (table) A table containing new filetype maps (see example). +---@param filetypes vim.filetype.add.filetypes A table containing new filetype maps (see example). function M.add(filetypes) for k, v in pairs(filetypes.extension or {}) do extension[k] = v @@ -2272,8 +2273,23 @@ local function match_pattern(name, path, tail, pat) end --- @class vim.filetype.match.args +--- @inlinedoc +--- +--- Buffer number to use for matching. Mutually exclusive with {contents} --- @field buf? integer +--- +--- Filename to use for matching. When {buf} is given, +--- defaults to the filename of the given buffer number. The +--- file need not actually exist in the filesystem. When used +--- without {buf} only the name of the file is used for +--- filetype matching. This may result in failure to detect +--- the filetype in cases where the filename alone is not +--- enough to disambiguate the filetype. --- @field filename? string +--- +--- An array of lines representing file contents to use for +--- matching. Can be used with {filename}. Mutually exclusive +--- with {buf}. --- @field contents? string[] --- Perform filetype detection. @@ -2305,20 +2321,8 @@ end --- vim.filetype.match({ contents = {'#!/usr/bin/env bash'} }) --- ``` --- ----@param args vim.filetype.match.args (table) Table specifying which matching strategy to use. +---@param args vim.filetype.match.args Table specifying which matching strategy to use. --- Accepted keys are: ---- * buf (number): Buffer number to use for matching. Mutually exclusive with ---- {contents} ---- * filename (string): Filename to use for matching. When {buf} is given, ---- defaults to the filename of the given buffer number. The ---- file need not actually exist in the filesystem. When used ---- without {buf} only the name of the file is used for ---- filetype matching. This may result in failure to detect ---- the filetype in cases where the filename alone is not ---- enough to disambiguate the filetype. ---- * contents (table): An array of lines representing file contents to use for ---- matching. Can be used with {filename}. Mutually exclusive ---- with {buf}. ---@return string|nil # If a match was found, the matched filetype. ---@return function|nil # A function that modifies buffer state when called (for example, to set some --- filetype specific buffer variables). The function accepts a buffer number as diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index 0af5fc4f30..a47b35e991 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -147,11 +147,29 @@ function M.dir(path, opts) end) end ---- @class vim.fs.find.opts +--- @class vim.fs.find.Opts +--- @inlinedoc +--- +--- Path to begin searching from. If +--- omitted, the |current-directory| is used. --- @field path string +--- +--- Search upward through parent directories. +--- Otherwise, search through child directories (recursively). +--- (default: `false`) --- @field upward boolean +--- +--- Stop searching when this directory is reached. +--- The directory itself is not searched. --- @field stop string +--- +--- Find only items of the given type. +--- If omitted, all items that match {names} are included. --- @field type string +--- +--- Stop the search after finding this many matches. +--- Use `math.huge` to place no limit on the number of matches. +--- (default: `1`) --- @field limit number --- Find files or directories (or other items as specified by `opts.type`) in the given path. @@ -194,23 +212,10 @@ end --- - path: full path of the current item --- The function should return `true` if the given item is considered a match. --- ----@param opts (table) Optional keyword arguments: ---- - path (string): Path to begin searching from. If ---- omitted, the |current-directory| is used. ---- - upward (boolean, default false): If true, search ---- upward through parent directories. Otherwise, ---- search through child directories ---- (recursively). ---- - stop (string): Stop searching when this directory is ---- reached. The directory itself is not searched. ---- - type (string): Find only items of the given type. ---- If omitted, all items that match {names} are included. ---- - limit (number, default 1): Stop the search after ---- finding this many matches. Use `math.huge` to ---- place no limit on the number of matches. +---@param opts vim.fs.find.Opts Optional keyword arguments: ---@return (string[]) # Normalized paths |vim.fs.normalize()| of all matching items function M.find(names, opts) - opts = opts or {} --[[@as vim.fs.find.opts]] + opts = opts or {} vim.validate({ names = { names, { 's', 't', 'f' } }, path = { opts.path, 's', true }, @@ -318,6 +323,13 @@ function M.find(names, opts) return matches end +--- @class vim.fs.normalize.Opts +--- @inlinedoc +--- +--- Expand environment variables. +--- (default: `true`) +--- @field expand_env boolean + --- Normalize a path to a standard format. A tilde (~) character at the --- beginning of the path is expanded to the user's home directory and any --- backslash (\) characters are converted to forward slashes (/). Environment @@ -337,9 +349,8 @@ end --- ``` --- ---@param path (string) Path to normalize ----@param opts table|nil Options: ---- - expand_env: boolean Expand environment variables (default: true) ----@return (string) Normalized path +---@param opts? vim.fs.normalize.Opts +---@return (string) : Normalized path function M.normalize(path, opts) opts = opts or {} diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index 798428014d..09de969b5b 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -64,11 +64,13 @@ --- In addition to the |vim.iter()| function, the |vim.iter| module provides --- convenience functions like |vim.iter.filter()| and |vim.iter.totable()|. +---@nodoc ---@class IterMod ---@operator call:Iter local M = {} +---@nodoc ---@class Iter local Iter = {} Iter.__index = Iter @@ -77,6 +79,7 @@ Iter.__call = function(self) end --- Special case implementations for iterators on list tables. +---@nodoc ---@class ListIter : Iter ---@field _table table Underlying table data ---@field _head number Index to the front of a table iterator diff --git a/runtime/lua/vim/loader.lua b/runtime/lua/vim/loader.lua index 5f3da55544..0d708ca1eb 100644 --- a/runtime/lua/vim/loader.lua +++ b/runtime/lua/vim/loader.lua @@ -10,16 +10,37 @@ local M = {} ---@alias CacheHash {mtime: {nsec: integer, sec: integer}, size: integer, type?: uv.aliases.fs_stat_types} ---@alias CacheEntry {hash:CacheHash, chunk:string} ----@class ModuleFindOpts ----@field all? boolean Search for all matches (defaults to `false`) ----@field rtp? boolean Search for modname in the runtime path (defaults to `true`) ----@field patterns? string[] Patterns to use (defaults to `{"/init.lua", ".lua"}`) ----@field paths? string[] Extra paths to search for modname - ----@class ModuleInfo ----@field modpath string Path of the module ----@field modname string Name of the module ----@field stat? uv.uv_fs_t File stat of the module path +--- @class vim.loader.find.Opts +--- @inlinedoc +--- +--- Search for modname in the runtime path. +--- (default: `true`) +--- @field rtp? boolean +--- +--- Extra paths to search for modname +--- (default: `{}`) +--- @field paths? string[] +--- +--- List of patterns to use when searching for modules. +--- A pattern is a string added to the basename of the Lua module being searched. +--- (default: `{"/init.lua", ".lua"}`) +--- @field patterns? string[] +--- +--- Search for all matches. +--- (default: `false`) +--- @field all? boolean + +--- @class vim.loader.ModuleInfo +--- @inlinedoc +--- +--- Path of the module +--- @field modpath string +--- +--- Name of the module +--- @field modname string +--- +--- The fs_stat of the module path. Won't be returned for `modname="*"` +--- @field stat? uv.uv_fs_t ---@alias LoaderStats table @@ -29,14 +50,14 @@ M.path = vim.fn.stdpath('cache') .. '/luac' ---@nodoc M.enabled = false ----@class Loader ----@field _rtp string[] ----@field _rtp_pure string[] ----@field _rtp_key string ----@field _hashes? table +---@class (private) Loader +---@field private _rtp string[] +---@field private _rtp_pure string[] +---@field private _rtp_key string +---@field private _hashes? table local Loader = { VERSION = 4, - ---@type table> + ---@type table> _indexed = {}, ---@type table _topmods = {}, @@ -270,17 +291,8 @@ end --- Finds Lua modules for the given module name. ---@param modname string Module name, or `"*"` to find the top-level modules instead ----@param opts? ModuleFindOpts (table) Options for finding a module: ---- - rtp: (boolean) Search for modname in the runtime path (defaults to `true`) ---- - paths: (string[]) Extra paths to search for modname (defaults to `{}`) ---- - patterns: (string[]) List of patterns to use when searching for modules. ---- A pattern is a string added to the basename of the Lua module being searched. ---- (defaults to `{"/init.lua", ".lua"}`) ---- - all: (boolean) Return all matches instead of just the first one (defaults to `false`) ----@return ModuleInfo[] (table) A list of results with the following properties: ---- - modpath: (string) the path to the module ---- - modname: (string) the name of the module ---- - stat: (table|nil) the fs_stat of the module path. Won't be returned for `modname="*"` +---@param opts? vim.loader.find.Opts Options for finding a module: +---@return vim.loader.ModuleInfo[] function M.find(modname, opts) opts = opts or {} @@ -306,7 +318,7 @@ function M.find(modname, opts) patterns[p] = '/lua/' .. basename .. pattern end - ---@type ModuleInfo[] + ---@type vim.loader.ModuleInfo[] local results = {} -- Only continue if we haven't found anything yet or we want to find all @@ -472,12 +484,12 @@ function Loader.track(stat, f) end end ----@class ProfileOpts +---@class (private) vim.loader._profile.Opts ---@field loaders? boolean Add profiling to the loaders --- Debug function that wraps all loaders and tracks stats ---@private ----@param opts ProfileOpts? +---@param opts vim.loader._profile.Opts? function M._profile(opts) Loader.get_rtp = Loader.track('get_rtp', Loader.get_rtp) Loader.read = Loader.track('read', Loader.read) diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 19497e40dc..8ebf4de3cb 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -108,12 +108,12 @@ function lsp._buf_get_line_ending(bufnr) end -- Tracks all clients created via lsp.start_client -local active_clients = {} --- @type table +local active_clients = {} --- @type table local all_buffer_active_clients = {} --- @type table> -local uninitialized_clients = {} --- @type table +local uninitialized_clients = {} --- @type table ---@param bufnr? integer ----@param fn fun(client: lsp.Client, client_id: integer, bufnr: integer) +---@param fn fun(client: vim.lsp.Client, client_id: integer, bufnr: integer) local function for_each_buffer_client(bufnr, fn, restrict_client_ids) validate({ fn = { fn, 'f' }, @@ -200,105 +200,15 @@ local function once(fn) end end --- FIXME: DOC: Shouldn't need to use a dummy function --- ---- LSP client object. You can get an active client object via ---- |vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|. +--- @class vim.lsp.start.Opts +--- @inlinedoc --- ---- - Methods: ---- - request(method, params, [handler], bufnr) ---- Sends a request to the server. ---- This is a thin wrapper around {client.rpc.request} with some additional ---- checking. ---- If {handler} is not specified, If one is not found there, then an error will occur. ---- Returns: {status}, {[client_id]}. {status} is a boolean indicating if ---- the notification was successful. If it is `false`, then it will always ---- be `false` (the client has shutdown). ---- If {status} is `true`, the function returns {request_id} as the second ---- result. You can use this with `client.cancel_request(request_id)` ---- to cancel the request. +--- Predicate used to decide if a client should be re-used. Used on all +--- running clients. The default implementation re-uses a client if name and +--- root_dir matches. +--- @field reuse_client fun(client: vim.lsp.Client, config: table): boolean --- ---- - request_sync(method, params, timeout_ms, bufnr) ---- Sends a request to the server and synchronously waits for the response. ---- This is a wrapper around {client.request} ---- Returns: { err=err, result=result }, a dictionary, where `err` and `result` come from ---- the |lsp-handler|. On timeout, cancel or error, returns `(nil, err)` where `err` is a ---- string describing the failure reason. If the request was unsuccessful returns `nil`. ---- ---- - notify(method, params) ---- Sends a notification to an LSP server. ---- Returns: a boolean to indicate if the notification was successful. If ---- it is false, then it will always be false (the client has shutdown). ---- ---- - cancel_request(id) ---- Cancels a request with a given request id. ---- Returns: same as `notify()`. ---- ---- - stop([force]) ---- Stops 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() ---- Checks whether a client is stopped. ---- Returns: true if the client is fully stopped. ---- ---- - on_attach(client, bufnr) ---- Runs the on_attach function from the client's config if it was defined. ---- Useful for buffer-local setup. ---- ---- - supports_method(method, [opts]): boolean ---- Checks if a client supports a given method. ---- Always returns true for unknown off-spec methods. ---- [opts] is a optional `{bufnr?: integer}` table. ---- Some language server capabilities can be file specific. ---- ---- - 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. ---- ---- - {rpc} (table): RPC client object, for low level interaction with the ---- client. See |vim.lsp.rpc.start()|. ---- ---- - {offset_encoding} (string): The encoding used for communicating ---- with the server. You can modify this in the `config`'s `on_init` method ---- before text is sent to the server. ---- ---- - {handlers} (table): The handlers used by the client as described in |lsp-handler|. ---- ---- - {commands} (table): Table of command name to function which is called if ---- any LSP action (code action, code lenses, ...) triggers the command. ---- Client commands take precedence over the global command registry. ---- ---- - {requests} (table): The current pending requests in flight ---- to the server. Entries are key-value pairs with the key ---- being the request ID while the value is a table with `type`, ---- `bufnr`, and `method` key-value pairs. `type` is either "pending" ---- for an active request, or "cancel" for a cancel request. It will ---- be "complete" ephemerally while executing |LspRequest| autocmds ---- when replies are received from the server. ---- ---- - {config} (table): Reference 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. ---- ---- - {progress} A ring buffer (|vim.ringbuf()|) containing progress messages ---- sent by the server. ---- ---- - {settings} Map with language server specific settings. ---- See {config} in |vim.lsp.start_client()| ---- ---- - {flags} A table with flags for the client. See {config} in |vim.lsp.start_client()| -lsp.client = nil - ---- @class lsp.StartOpts ---- @field reuse_client fun(client: lsp.Client, config: table): boolean +--- Buffer handle to attach to if starting or re-using a client (0 for current). --- @field bufnr integer --- Create a new LSP client and start a language server or reuses an already @@ -337,17 +247,9 @@ lsp.client = nil --- Either use |:au|, |nvim_create_autocmd()| or put the call in a --- `ftplugin/.lua` (See |ftplugin-name|) --- ----@param config lsp.ClientConfig Same configuration as documented in |vim.lsp.start_client()| ----@param opts lsp.StartOpts? Optional keyword arguments: ---- - reuse_client (fun(client: client, config: table): boolean) ---- Predicate used to decide if a client should be re-used. ---- Used on all running clients. ---- The default implementation re-uses a client if name ---- and root_dir matches. ---- - bufnr (number) ---- Buffer handle to attach to if starting or re-using a ---- client (0 for current). ----@return integer? client_id +--- @param config vim.lsp.ClientConfig Configuration for the server. +--- @param opts vim.lsp.start.Opts? Optional keyword arguments +--- @return integer? client_id function lsp.start(config, opts) opts = opts or {} local reuse_client = opts.reuse_client @@ -428,7 +330,7 @@ local function is_empty_or_default(bufnr, option) end ---@private ----@param client lsp.Client +---@param client vim.lsp.Client ---@param bufnr integer function lsp._set_defaults(client, bufnr) if @@ -482,7 +384,7 @@ local function reset_defaults(bufnr) end) end ---- @param client lsp.Client +--- @param client vim.lsp.Client local function on_client_init(client) local id = client.id uninitialized_clients[id] = nil @@ -552,121 +454,9 @@ local function on_client_exit(code, signal, client_id) end) end --- FIXME: DOC: Currently all methods on the `vim.lsp.client` object are --- documented twice: Here, and on the methods themselves (e.g. --- `client.request()`). This is a workaround for the vimdoc generator script --- not handling method names correctly. If you change the documentation on --- either, please make sure to update the other as well. --- --- Starts and initializes a client with the given configuration. ---- ---- Field `cmd` in {config} is required. ---- ----@param config (lsp.ClientConfig) Configuration for the server: ---- - cmd: (string[]|fun(dispatchers: table):table) command string[] that launches the language ---- server (treated as in |jobstart()|, must be absolute or on `$PATH`, shell constructs like ---- "~" are not expanded), or function that creates an RPC client. Function receives ---- a `dispatchers` table and returns a table with member functions `request`, `notify`, ---- `is_closing` and `terminate`. ---- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|. ---- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()| ---- ---- - 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. Must be specified using a table. ---- Non-string values are coerced to string. ---- Example: ---- ``` ---- { PORT = 8080; HOST = "0.0.0.0"; } ---- ``` ---- ---- - detached: (boolean, default true) Daemonize the server process so that it runs in a ---- separate process group from Nvim. Nvim will shutdown the process on exit, but if Nvim fails to ---- exit cleanly this could leave behind orphaned server processes. ---- ---- - workspace_folders: (table) List of workspace folders passed to the ---- language server. For backwards compatibility rootUri and rootPath will be ---- derived from the first workspace folder in this list. See `workspaceFolders` in ---- the LSP spec. ---- ---- - 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.empty_dict()|, else it will be encoded as an ---- array. ---- ---- - handlers: Map of language server method names to |lsp-handler| ---- ---- - settings: Map with language server specific settings. These are ---- returned to the language server if requested via `workspace/configuration`. ---- Keys are case-sensitive. ---- ---- - commands: table Table that maps string of clientside commands to user-defined functions. ---- Commands passed to start_client take precedence over the global command registry. Each key ---- must be a unique command name, and the value is a function which is called if any LSP action ---- (code action, code lenses, ...) triggers the command. ---- ---- - 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. ---- ---- - get_language_id: function(bufnr, filetype) -> language ID as string. ---- Defaults to the filetype. ---- ---- - 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.rpc.client_errors` for possible errors. ---- Use `vim.lsp.rpc.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 |vim.lsp.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" ---- ---- - flags: A table with flags for the client. The current (experimental) flags are: ---- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits ---- - debounce_text_changes (number, default 150): Debounce didChange ---- notifications to the server by the given number in milliseconds. No debounce ---- occurs if nil ---- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to ---- exit cleanly after sending the "shutdown" request before sending kill -15. ---- If set to false, nvim exits immediately after sending the "shutdown" request to the server. ---- ---- - root_dir: (string) Directory where the LSP ---- server will base its workspaceFolders, rootUri, and rootPath ---- on initialization. ---- ----@return integer|nil client_id. |vim.lsp.get_client_by_id()| Note: client may not be +--- @param config vim.lsp.ClientConfig Configuration for the server. +--- @return integer|nil client_id |vim.lsp.get_client_by_id()| Note: client may not be --- fully initialized. Use `on_init` to do any actions once --- the client has been initialized. function lsp.start_client(config) @@ -927,7 +717,7 @@ end --- ---@param client_id integer client id --- ----@return (nil|lsp.Client) client rpc object +---@return (nil|vim.lsp.Client) client rpc object function lsp.get_client_by_id(client_id) return active_clients[client_id] or uninitialized_clients[client_id] end @@ -943,7 +733,7 @@ end --- Stops a client(s). --- ---- You can also use the `stop()` function on a |vim.lsp.client| object. +--- You can also use the `stop()` function on a |vim.lsp.Client| object. --- To stop all clients: --- --- ```lua @@ -953,7 +743,7 @@ end --- By default asks the server to shutdown, unless stop was requested --- already for this client, then force-shutdown is attempted. --- ----@param client_id integer|table id or |vim.lsp.client| object, or list thereof +---@param client_id integer|vim.lsp.Client id or |vim.lsp.Client| object, or list thereof ---@param force boolean|nil shutdown forcefully function lsp.stop_client(client_id, force) local ids = type(client_id) == 'table' and client_id or { client_id } @@ -968,28 +758,32 @@ function lsp.stop_client(client_id, force) end end ----@class vim.lsp.get_clients.filter ----@field id integer|nil Match clients by id ----@field bufnr integer|nil match clients attached to the given buffer ----@field name string|nil match clients by name ----@field method string|nil match client by supported method name +--- Key-value pairs used to filter the returned clients. +--- @class vim.lsp.get_clients.Filter +--- @inlinedoc +--- +--- Only return clients with the given id +--- @field id? integer +--- +--- Only return clients attached to this buffer +--- @field bufnr? integer +--- +--- Only return clients with the given name +--- @field name? string +--- +--- Only return clients supporting the given method +--- @field method? string --- Get active clients. --- ----@param filter vim.lsp.get_clients.filter|nil (table|nil) A table with ---- key-value pairs used to filter the returned clients. ---- The available keys are: ---- - id (number): Only return clients with the given id ---- - bufnr (number): Only return clients attached to this buffer ---- - name (string): Only return clients with the given name ---- - method (string): Only return clients supporting the given method ----@return lsp.Client[]: List of |vim.lsp.client| objects +---@param filter? vim.lsp.get_clients.Filter +---@return vim.lsp.Client[]: List of |vim.lsp.Client| objects function lsp.get_clients(filter) validate({ filter = { filter, 't', true } }) filter = filter or {} - local clients = {} --- @type lsp.Client[] + local clients = {} --- @type vim.lsp.Client[] local t = filter.bufnr and (all_buffer_active_clients[resolve_bufnr(filter.bufnr)] or {}) or active_clients @@ -1233,15 +1027,20 @@ function lsp.omnifunc(findstart, base) return vim.lsp._completion.omnifunc(findstart, base) end +--- @class vim.lsp.formatexpr.Opts +--- @inlinedoc +--- +--- The timeout period for the formatting request. +--- (default: 500ms). +--- @field timeout_ms integer + --- Provides an interface between the built-in client and a `formatexpr` function. --- --- Currently only supports a single client. This can be set via --- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach` --- via `vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`. --- ----@param opts table options for customizing the formatting expression which takes the ---- following optional keys: ---- * timeout_ms (default 500ms). The timeout period for the formatting request. +---@param opts? vim.lsp.formatexpr.Opts function lsp.formatexpr(opts) opts = opts or {} local timeout_ms = opts.timeout_ms or 500 @@ -1313,14 +1112,14 @@ function lsp.client_is_stopped(client_id) end --- Gets a map of client_id:client pairs for the given buffer, where each value ---- is a |vim.lsp.client| object. +--- is a |vim.lsp.Client| object. --- ---@param bufnr (integer|nil): Buffer handle, or 0 for current ---@return table result is table of (client_id, client) pairs ---@deprecated Use |vim.lsp.get_clients()| instead. function lsp.buf_get_clients(bufnr) vim.deprecate('vim.lsp.buf_get_clients()', 'vim.lsp.get_clients()', '0.12') - local result = {} --- @type table + local result = {} --- @type table for _, client in ipairs(lsp.get_clients({ bufnr = resolve_bufnr(bufnr) })) do result[client.id] = client end diff --git a/runtime/lua/vim/lsp/_changetracking.lua b/runtime/lua/vim/lsp/_changetracking.lua index 3ecdec1659..b2be53269f 100644 --- a/runtime/lua/vim/lsp/_changetracking.lua +++ b/runtime/lua/vim/lsp/_changetracking.lua @@ -61,7 +61,7 @@ local state_by_group = setmetatable({}, { end, }) ----@param client lsp.Client +---@param client vim.lsp.Client ---@return vim.lsp.CTGroup local function get_group(client) local allow_inc_sync = vim.F.if_nil(client.flags.allow_incremental_sync, true) --- @type boolean @@ -127,7 +127,7 @@ local function incremental_changes(state, encoding, bufnr, firstline, lastline, return incremental_change end ----@param client lsp.Client +---@param client vim.lsp.Client ---@param bufnr integer function M.init(client, bufnr) assert(client.offset_encoding, 'lsp client must have an offset_encoding') @@ -165,7 +165,7 @@ function M.init(client, bufnr) end end ---- @param client lsp.Client +--- @param client vim.lsp.Client --- @param bufnr integer --- @param name string --- @return string @@ -189,7 +189,7 @@ local function reset_timer(buf_state) end end ---- @param client lsp.Client +--- @param client vim.lsp.Client --- @param bufnr integer function M.reset_buf(client, bufnr) M.flush(client, bufnr) @@ -207,7 +207,7 @@ function M.reset_buf(client, bufnr) end end ---- @param client lsp.Client +--- @param client vim.lsp.Client function M.reset(client) local state = state_by_group[get_group(client)] if not state then @@ -350,7 +350,7 @@ function M.send_changes(bufnr, firstline, lastline, new_lastline) end --- Flushes any outstanding change notification. ----@param client lsp.Client +---@param client vim.lsp.Client ---@param bufnr? integer function M.flush(client, bufnr) local group = get_group(client) diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index d2e92de083..377c8680c7 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -11,7 +11,7 @@ local M = {} --- ---@param method (string) LSP method name ---@param params (table|nil) Parameters to send to the server ----@param handler (function|nil) See |lsp-handler|. Follows |lsp-handler-resolution| +---@param handler lsp.Handler? See |lsp-handler|. Follows |lsp-handler-resolution| --- ---@return table client_request_ids Map of client-id:request-id pairs ---for all successful requests. @@ -31,7 +31,7 @@ end --- Checks whether the language servers attached to the current buffer are --- ready. --- ----@return boolean if server responds. +---@return boolean : if server responds. ---@deprecated function M.server_ready() vim.deprecate('vim.lsp.buf.server_ready()', nil, '0.10') @@ -57,35 +57,57 @@ local function request_with_options(name, params, options) request(name, params, req_handler) end ---- Jumps to the declaration of the symbol under the cursor. ----@note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead. +--- @class vim.lsp.ListOpts +--- +--- list-handler replacing the default handler. +--- Called for any non-empty result. +--- This table can be used with |setqflist()| or |setloclist()|. E.g.: +--- ```lua +--- local function on_list(options) +--- vim.fn.setqflist({}, ' ', options) +--- vim.cmd.cfirst() +--- end --- ----@param options table|nil additional options ---- - reuse_win: (boolean) Jump to existing window if buffer is already open. ---- - on_list: (function) |lsp-on-list-handler| replacing the default handler. ---- Called for any non-empty result. +--- vim.lsp.buf.definition({ on_list = on_list }) +--- vim.lsp.buf.references(nil, { on_list = on_list }) +--- ``` +--- +--- If you prefer loclist do something like this: +--- ```lua +--- local function on_list(options) +--- vim.fn.setloclist(0, {}, ' ', options) +--- vim.cmd.lopen() +--- end +--- ``` +--- @field on_list? fun(t: vim.lsp.LocationOpts.OnList) + +--- @class vim.lsp.LocationOpts.OnList +--- @field items table[] Structured like |setqflist-what| +--- @field title? string Title for the list. +--- @field context? table `ctx` from |lsp-handler| + +--- @class vim.lsp.LocationOpts: vim.lsp.ListOpts +--- +--- Jump to existing window if buffer is already open. +--- @field reuse_win? boolean + +--- Jumps to the declaration of the symbol under the cursor. +--- @note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead. +--- @param options? vim.lsp.LocationOpts function M.declaration(options) local params = util.make_position_params() request_with_options(ms.textDocument_declaration, params, options) end --- Jumps to the definition of the symbol under the cursor. ---- ----@param options table|nil additional options ---- - reuse_win: (boolean) Jump to existing window if buffer is already open. ---- - on_list: (function) |lsp-on-list-handler| replacing the default handler. ---- Called for any non-empty result. +--- @param options? vim.lsp.LocationOpts function M.definition(options) local params = util.make_position_params() request_with_options(ms.textDocument_definition, params, options) end --- Jumps to the definition of the type of the symbol under the cursor. ---- ----@param options table|nil additional options ---- - reuse_win: (boolean) Jump to existing window if buffer is already open. ---- - on_list: (function) |lsp-on-list-handler| replacing the default handler. ---- Called for any non-empty result. +--- @param options? vim.lsp.LocationOpts function M.type_definition(options) local params = util.make_position_params() request_with_options(ms.textDocument_typeDefinition, params, options) @@ -93,10 +115,7 @@ end --- Lists all the implementations for the symbol under the cursor in the --- quickfix window. ---- ----@param options table|nil additional options ---- - on_list: (function) |lsp-on-list-handler| replacing the default handler. ---- Called for any non-empty result. +--- @param options? vim.lsp.LocationOpts function M.implementation(options) local params = util.make_position_params() request_with_options(ms.textDocument_implementation, params, options) @@ -156,45 +175,55 @@ local function range_from_selection(bufnr, mode) } end +--- @class vim.lsp.buf.format.Opts +--- @inlinedoc +--- +--- Can be used to specify FormattingOptions. Some unspecified options will be +--- automatically derived from the current Nvim options. +--- See https://microsoft.github.io/language-server-protocol/specification/#formattingOptions +--- @field formatting_options? table +--- +--- Time in milliseconds to block for formatting requests. No effect if async=true. +--- (default: `1000`) +--- @field timeout_ms? integer +--- +--- Restrict formatting to the clients attached to the given buffer. +--- (default: current buffer) +--- @field bufnr? integer +--- +--- Predicate used to filter clients. Receives a client as argument and must +--- return a boolean. Clients matching the predicate are included. Example: +--- ```lua +--- -- Never request typescript-language-server for formatting +--- vim.lsp.buf.format { +--- filter = function(client) return client.name ~= "tsserver" end +--- } +--- ``` +--- @field filter? fun(client: vim.lsp.Client): boolean? +--- +--- If true the method won't block. +--- Editing the buffer while formatting asynchronous can lead to unexpected +--- changes. +--- (Default: false) +--- @field async? boolean +--- +--- Restrict formatting to the client with ID (client.id) matching this field. +--- @field id? integer +--- +--- Restrict formatting to the client with name (client.name) matching this field. +--- @field name? string +--- +--- Range to format. +--- Table must contain `start` and `end` keys with {row,col} tuples using +--- (1,0) indexing. +--- (Default: current selection in visual mode, `nil` in other modes, +--- formatting the full buffer) +--- @field range? {start:integer[],end:integer[]} + --- Formats a buffer using the attached (and optionally filtered) language --- server clients. --- ---- @param options table|nil Optional table which holds the following optional fields: ---- - formatting_options (table|nil): ---- Can be used to specify FormattingOptions. Some unspecified options will be ---- automatically derived from the current Nvim options. ---- See https://microsoft.github.io/language-server-protocol/specification/#formattingOptions ---- - timeout_ms (integer|nil, default 1000): ---- Time in milliseconds to block for formatting requests. No effect if async=true ---- - bufnr (number|nil): ---- Restrict formatting to the clients attached to the given buffer, defaults to the current ---- buffer (0). ---- ---- - filter (function|nil): ---- Predicate used to filter clients. Receives a client as argument and must return a ---- boolean. Clients matching the predicate are included. Example: ---- ```lua ---- -- Never request typescript-language-server for formatting ---- vim.lsp.buf.format { ---- filter = function(client) return client.name ~= "tsserver" end ---- } ---- ``` ---- ---- - async boolean|nil ---- If true the method won't block. Defaults to false. ---- Editing the buffer while formatting asynchronous can lead to unexpected ---- changes. ---- ---- - id (number|nil): ---- Restrict formatting to the client with ID (client.id) matching this field. ---- - name (string|nil): ---- Restrict formatting to the client with name (client.name) matching this field. ---- ---- - range (table|nil) Range to format. ---- Table must contain `start` and `end` keys with {row,col} tuples using ---- (1,0) indexing. ---- Defaults to current selection in visual mode ---- Defaults to `nil` in other modes, formatting the full buffer +--- @param options? vim.lsp.buf.format.Opts function M.format(options) options = options or {} local bufnr = options.bufnr or api.nvim_get_current_buf() @@ -229,8 +258,7 @@ function M.format(options) end if options.async then - local do_format - do_format = function(idx, client) + local function do_format(idx, client) if not client then return end @@ -256,17 +284,22 @@ function M.format(options) end end +--- @class vim.lsp.buf.rename.Opts +--- @inlinedoc +--- +--- Predicate used to filter clients. Receives a client as argument and +--- must return a boolean. Clients matching the predicate are included. +--- @field filter? fun(client: vim.lsp.Client): boolean? +--- +--- Restrict clients used for rename to ones where client.name matches +--- this field. +--- @field name? string + --- Renames all references to the symbol under the cursor. --- ---@param new_name string|nil If not provided, the user will be prompted for a new --- name using |vim.ui.input()|. ----@param options table|nil additional options ---- - filter (function|nil): ---- Predicate used to filter clients. Receives a client as argument and ---- must return a boolean. Clients matching the predicate are included. ---- - name (string|nil): ---- Restrict clients used for rename to ones where client.name matches ---- this field. +---@param options? vim.lsp.buf.rename.Opts Additional options: function M.rename(new_name, options) options = options or {} local bufnr = options.bufnr or api.nvim_get_current_buf() @@ -386,8 +419,7 @@ end --- ---@param context (table|nil) Context for the request ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references ----@param options table|nil additional options ---- - on_list: (function) handler for list results. See |lsp-on-list-handler| +---@param options? vim.lsp.ListOpts function M.references(context, options) validate({ context = { context, 't', true } }) local params = util.make_position_params() @@ -398,14 +430,13 @@ function M.references(context, options) end --- Lists all symbols in the current buffer in the quickfix window. ---- ----@param options table|nil additional options ---- - on_list: (function) handler for list results. See |lsp-on-list-handler| +--- @param options? vim.lsp.ListOpts function M.document_symbol(options) local params = { textDocument = util.make_text_document_params() } request_with_options(ms.textDocument_documentSymbol, params, options) end +--- @param call_hierarchy_items lsp.CallHierarchyItem[]? local function pick_call_hierarchy_item(call_hierarchy_items) if not call_hierarchy_items then return @@ -425,8 +456,10 @@ local function pick_call_hierarchy_item(call_hierarchy_items) return choice end +--- @param method string local function call_hierarchy(method) local params = util.make_position_params() + --- @param result lsp.CallHierarchyItem[]? request(ms.textDocument_prepareCallHierarchy, params, function(err, result, ctx) if err then vim.notify(err.message, vim.log.levels.WARN) @@ -545,9 +578,8 @@ end --- call, the user is prompted to enter a string on the command line. An empty --- string means no filtering is done. --- ----@param query string|nil optional ----@param options table|nil additional options ---- - on_list: (function) handler for list results. See |lsp-on-list-handler| +--- @param query string? optional +--- @param options? vim.lsp.ListOpts function M.workspace_symbol(query, options) query = query or npcall(vim.fn.input, 'Query: ') if query == nil then @@ -582,16 +614,36 @@ function M.clear_references() util.buf_clear_references() end +---@nodoc ---@class vim.lsp.CodeActionResultEntry ---@field error? lsp.ResponseError ---@field result? (lsp.Command|lsp.CodeAction)[] ---@field ctx lsp.HandlerContext ----@class vim.lsp.buf.code_action.opts ----@field context? lsp.CodeActionContext ----@field filter? fun(x: lsp.CodeAction|lsp.Command):boolean ----@field apply? boolean ----@field range? {start: integer[], end: integer[]} +--- @class vim.lsp.buf.code_action.Opts +--- @inlinedoc +--- +--- Corresponds to `CodeActionContext` of the LSP specification: +--- - {diagnostics}? (`table`) LSP `Diagnostic[]`. Inferred from the current +--- position if not provided. +--- - {only}? (`table`) List of LSP `CodeActionKind`s used to filter the code actions. +--- Most language servers support values like `refactor` +--- or `quickfix`. +--- - {triggerKind}? (`integer`) The reason why code actions were requested. +--- @field context? lsp.CodeActionContext +--- +--- Predicate taking an `CodeAction` and returning a boolean. +--- @field filter? fun(x: lsp.CodeAction|lsp.Command):boolean +--- +--- When set to `true`, and there is just one remaining action +--- (after filtering), the action is applied without user query. +--- @field apply? boolean +--- +--- Range for which code actions should be requested. +--- If in visual mode this defaults to the active selection. +--- Table must contain `start` and `end` keys with {row,col} tuples +--- using mark-like indexing. See |api-indexing| +--- @field range? {start: integer[], end: integer[]} --- This is not public because the main extension point is --- vim.ui.select which can be overridden independently. @@ -602,7 +654,7 @@ end --- need to be able to link a `CodeAction|Command` to the right client for --- `codeAction/resolve` ---@param results table ----@param opts? vim.lsp.buf.code_action.opts +---@param opts? vim.lsp.buf.code_action.Opts local function on_code_action_results(results, opts) ---@param a lsp.Command|lsp.CodeAction local function action_filter(a) @@ -647,14 +699,15 @@ local function on_code_action_results(results, opts) end ---@param action lsp.Command|lsp.CodeAction - ---@param client lsp.Client + ---@param client vim.lsp.Client ---@param ctx lsp.HandlerContext local function apply_action(action, client, ctx) if action.edit then util.apply_workspace_edit(action.edit, client.offset_encoding) end - if action.command then - local command = type(action.command) == 'table' and action.command or action + local a_cmd = action.command + if a_cmd then + local command = type(a_cmd) == 'table' and a_cmd or action client:_exec_cmd(command, ctx) end end @@ -676,7 +729,6 @@ local function on_code_action_results(results, opts) -- command: string -- arguments?: any[] -- - ---@type lsp.Client local client = assert(vim.lsp.get_client_by_id(choice.ctx.client_id)) local action = choice.action local bufnr = assert(choice.ctx.bufnr, 'Must have buffer number') @@ -726,29 +778,7 @@ end --- Selects a code action available at the current --- cursor position. --- ----@param options table|nil Optional table which holds the following optional fields: ---- - context: (table|nil) ---- Corresponds to `CodeActionContext` of the LSP specification: ---- - diagnostics (table|nil): ---- LSP `Diagnostic[]`. Inferred from the current ---- position if not provided. ---- - only (table|nil): ---- List of LSP `CodeActionKind`s used to filter the code actions. ---- Most language servers support values like `refactor` ---- or `quickfix`. ---- - triggerKind (number|nil): The reason why code actions were requested. ---- - filter: (function|nil) ---- Predicate taking an `CodeAction` and returning a boolean. ---- - apply: (boolean|nil) ---- When set to `true`, and there is just one remaining action ---- (after filtering), the action is applied without user query. ---- ---- - range: (table|nil) ---- Range for which code actions should be requested. ---- If in visual mode this defaults to the active selection. ---- Table must contain `start` and `end` keys with {row,col} tuples ---- using mark-like indexing. See |api-indexing| ---- +---@param options? vim.lsp.buf.code_action.Opts ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction ---@see vim.lsp.protocol.CodeActionTriggerKind function M.code_action(options) @@ -814,9 +844,8 @@ function M.code_action(options) end --- Executes an LSP server command. ---- ----@param command_params table A valid `ExecuteCommandParams` object ----@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand +--- @param command_params lsp.ExecuteCommandParams +--- @see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand function M.execute_command(command_params) validate({ command = { command_params.command, 's' }, diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index c1b41a7183..fcbaadbc57 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -6,38 +6,125 @@ local ms = lsp.protocol.Methods local changetracking = lsp._changetracking local validate = vim.validate ---- @alias vim.lsp.client.on_init_cb fun(client: lsp.Client, initialize_result: lsp.InitializeResult) ---- @alias vim.lsp.client.on_attach_cb fun(client: lsp.Client, bufnr: integer) +--- @alias vim.lsp.client.on_init_cb fun(client: vim.lsp.Client, initialize_result: lsp.InitializeResult) +--- @alias vim.lsp.client.on_attach_cb fun(client: vim.lsp.Client, bufnr: integer) --- @alias vim.lsp.client.on_exit_cb fun(code: integer, signal: integer, client_id: integer) ---- @alias vim.lsp.client.before_init_cb fun(params: lsp.InitializeParams, config: lsp.ClientConfig) - ---- @class lsp.ClientConfig +--- @alias vim.lsp.client.before_init_cb fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig) + +--- @class vim.lsp.ClientConfig +--- command string[] that launches the language +--- server (treated as in |jobstart()|, must be absolute or on `$PATH`, shell constructs like +--- "~" are not expanded), or function that creates an RPC client. Function receives +--- a `dispatchers` table and returns a table with member functions `request`, `notify`, +--- `is_closing` and `terminate`. +--- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|. +--- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()| --- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient? +--- +--- Directory to launch the `cmd` process. Not related to `root_dir`. +--- (default: cwd) --- @field cmd_cwd? string +--- +--- Environment flags to pass to the LSP on spawn. +--- Must be specified using a table. +--- Non-string values are coerced to string. +--- Example: +--- ```lua +--- { PORT = 8080; HOST = "0.0.0.0"; } +--- ``` --- @field cmd_env? table +--- +--- Daemonize the server process so that it runs in a separate process group from Nvim. +--- Nvim will shutdown the process on exit, but if Nvim fails to exit cleanly this could leave +--- behind orphaned server processes. +--- (default: true) --- @field detached? boolean +--- +--- List of workspace folders passed to the language server. +--- For backwards compatibility rootUri and rootPath will be derived from the first workspace +--- folder in this list. See `workspaceFolders` in the LSP spec. --- @field workspace_folders? lsp.WorkspaceFolder[] +--- +--- 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.empty_dict()|, else it will be encoded as an +--- array. --- @field capabilities? lsp.ClientCapabilities +--- +--- Map of language server method names to |lsp-handler| --- @field handlers? table +--- +--- Map with language server specific settings. These are returned to the language server if +--- requested via `workspace/configuration`. Keys are case-sensitive. --- @field settings? table +--- +--- Table that maps string of clientside commands to user-defined functions. +--- Commands passed to start_client take precedence over the global command registry. Each key +--- must be a unique command name, and the value is a function which is called if any LSP action +--- (code action, code lenses, ...) triggers the command. --- @field commands? table +--- +--- Values to pass in the initialization request as `initializationOptions`. See `initialize` in +--- the LSP spec. --- @field init_options? table +--- +--- Name in log messages. +--- (default: client-id) --- @field name? string +--- +--- Language ID as string. Defaults to the filetype. --- @field get_language_id? fun(bufnr: integer, filetype: string): string ---- @field offset_encoding? string +--- +--- The encoding that the LSP server expects. Client does not verify this is correct. +--- @field offset_encoding? 'utf-8'|'utf-16'|'utf-32' +--- +--- Callback 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.rpc.client_errors` +--- for possible errors. Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name. --- @field on_error? fun(code: integer, err: string) +--- +--- Callback 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 |vim.lsp.start_client()|. +--- You can use this to modify parameters before they are sent. --- @field before_init? vim.lsp.client.before_init_cb +--- +--- Callback 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. --- @field on_init? elem_or_list +--- +--- Callback invoked on client exit. +--- - code: exit code of the process +--- - signal: number describing the signal used to terminate (if any) +--- - client_id: client handle --- @field on_exit? elem_or_list +--- +--- Callback invoked when client attaches to a buffer. --- @field on_attach? elem_or_list +--- +--- Passed directly to the language server in the initialize request. Invalid/empty values will +--- (default: "off") --- @field trace? 'off'|'messages'|'verbose' +--- +--- A table with flags for the client. The current (experimental) flags are: +--- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits +--- - debounce_text_changes (number, default 150): Debounce didChange +--- notifications to the server by the given number in milliseconds. No debounce +--- occurs if nil +--- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to +--- exit cleanly after sending the "shutdown" request before sending kill -15. +--- If set to false, nvim exits immediately after sending the "shutdown" request to the server. --- @field flags? table +--- +--- Directory where the LSP server will base its workspaceFolders, rootUri, and rootPath on initialization. --- @field root_dir? string ---- @class lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}> +--- @class vim.lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}> --- @field pending table ---- @class lsp.Client +--- @class vim.lsp.Client --- --- The id allocated to the client. --- @field id integer @@ -67,7 +154,7 @@ local validate = vim.validate --- --- copy of the table that was passed by the user --- to |vim.lsp.start_client()|. ---- @field config lsp.ClientConfig +--- @field config vim.lsp.ClientConfig --- --- Response from the server sent on --- initialize` describing the server's capabilities. @@ -75,7 +162,7 @@ local validate = vim.validate --- --- A ring buffer (|vim.ringbuf()|) containing progress messages --- sent by the server. ---- @field progress lsp.Client.Progress +--- @field progress vim.lsp.Client.Progress --- --- @field initialized true? --- @@ -239,7 +326,7 @@ local function default_get_language_id(_bufnr, filetype) end --- Validates a client configuration as given to |vim.lsp.start_client()|. ---- @param config lsp.ClientConfig +--- @param config vim.lsp.ClientConfig local function validate_config(config) validate({ config = { config, 't' }, @@ -285,7 +372,7 @@ local function get_trace(trace) end --- @param id integer ---- @param config lsp.ClientConfig +--- @param config vim.lsp.ClientConfig --- @return string local function get_name(id, config) local name = config.name @@ -328,8 +415,8 @@ local function ensure_list(x) end --- @package ---- @param config lsp.ClientConfig ---- @return lsp.Client? +--- @param config vim.lsp.ClientConfig +--- @return vim.lsp.Client? function Client.create(config) validate_config(config) @@ -337,7 +424,7 @@ function Client.create(config) local id = client_index local name = get_name(id, config) - --- @class lsp.Client + --- @class vim.lsp.Client local self = { id = id, config = config, @@ -370,7 +457,7 @@ function Client.create(config) --- - lsp.WorkDoneProgressBegin, --- - lsp.WorkDoneProgressReport (extended with title from Begin) --- - lsp.WorkDoneProgressEnd (extended with title from Begin) - progress = vim.ringbuf(50) --[[@as lsp.Client.Progress]], + progress = vim.ringbuf(50) --[[@as vim.lsp.Client.Progress]], --- @deprecated use client.progress instead messages = { name = name, messages = {}, progress = {}, status = {} }, @@ -421,6 +508,7 @@ function Client.create(config) return self end +--- @private --- @param cbs function[] --- @param error_id integer --- @param ... any @@ -698,7 +786,7 @@ function Client:_cancel_request(id) return self.rpc.notify(ms.dollar_cancelRequest, { id = id }) end ---- @nodoc +--- @private --- Stops a client, optionally with force. --- --- By default, it will just ask the - server to shutdown without force. If @@ -853,6 +941,7 @@ function Client:write_error(code, err) err_message(self._log_prefix, ': Error ', client_error, ': ', vim.inspect(err)) end +--- @private --- @param method string --- @param opts? {bufnr: integer?} function Client:_supports_method(method, opts) diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index 7aed6f99e3..48c096c0c1 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -279,7 +279,8 @@ function M.on_codelens(err, result, ctx, _) end) end ---- @class vim.lsp.codelens.RefreshOptions +--- @class vim.lsp.codelens.refresh.Opts +--- @inlinedoc --- @field bufnr integer? filter by buffer. All buffers if nil, 0 for current buffer --- Refresh the lenses. @@ -292,8 +293,7 @@ end --- autocmd BufEnter,CursorHold,InsertLeave lua vim.lsp.codelens.refresh({ bufnr = 0 }) --- ``` --- ---- @param opts? vim.lsp.codelens.RefreshOptions Table with the following fields: ---- - `bufnr` (integer|nil): filter by buffer. All buffers if nil, 0 for current buffer +--- @param opts? vim.lsp.codelens.refresh.Opts Optional fields function M.refresh(opts) opts = opts or {} local bufnr = opts.bufnr and resolve_bufnr(opts.bufnr) diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 1fa67fc473..6156821093 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -390,7 +390,7 @@ local function clear(bufnr) end end ----@class lsp.diagnostic.bufstate +---@class (private) lsp.diagnostic.bufstate ---@field enabled boolean Whether inlay hints are enabled for this buffer ---@type table local bufstates = {} diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 781d720486..d816fb1482 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -412,6 +412,7 @@ M[ms.textDocument_hover] = M.hover ---@param _ nil not used ---@param result (table) result of LSP method; a location or a list of locations. ---@param ctx (lsp.HandlerContext) table containing the context of the request, including the method +---@param config? vim.lsp.buf.LocationOpts ---(`textDocument/definition` can return `Location` or `Location[]` local function location_handler(_, result, ctx, config) if result == nil or vim.tbl_isempty(result) then diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua index 49dc35fdf6..ec676ea97f 100644 --- a/runtime/lua/vim/lsp/inlay_hint.lua +++ b/runtime/lua/vim/lsp/inlay_hint.lua @@ -4,12 +4,12 @@ local ms = require('vim.lsp.protocol').Methods local api = vim.api local M = {} ----@class lsp.inlay_hint.bufstate +---@class (private) vim.lsp.inlay_hint.bufstate ---@field version? integer ---@field client_hints? table> client_id -> (lnum -> hints) ---@field applied table Last version of hints applied to this line ---@field enabled boolean Whether inlay hints are enabled for this buffer ----@type table +---@type table local bufstates = {} local namespace = api.nvim_create_namespace('vim_lsp_inlayhint') @@ -103,11 +103,14 @@ function M.on_refresh(err, _, ctx, _) return vim.NIL end ---- @class vim.lsp.inlay_hint.get.filter +--- Optional filters |kwargs|: +--- @class vim.lsp.inlay_hint.get.Filter +--- @inlinedoc --- @field bufnr integer? --- @field range lsp.Range? ---- + --- @class vim.lsp.inlay_hint.get.ret +--- @inlinedoc --- @field bufnr integer --- @field client_id integer --- @field inlay_hint lsp.InlayHint @@ -130,17 +133,8 @@ end --- }) --- ``` --- ---- @param filter vim.lsp.inlay_hint.get.filter? ---- Optional filters |kwargs|: ---- - bufnr (integer?): 0 for current buffer ---- - range (lsp.Range?) ---- +--- @param filter vim.lsp.inlay_hint.get.Filter? --- @return vim.lsp.inlay_hint.get.ret[] ---- Each list item is a table with the following fields: ---- - bufnr (integer) ---- - client_id (integer) ---- - inlay_hint (lsp.InlayHint) ---- --- @since 12 function M.get(filter) vim.validate({ filter = { filter, 'table', true } }) @@ -241,7 +235,7 @@ end --- Refresh inlay hints, only if we have attached clients that support it ---@param bufnr (integer) Buffer handle, or 0 for current ----@param opts? lsp.util.RefreshOptions Additional options to pass to util._refresh +---@param opts? vim.lsp.util._refresh.Opts Additional options to pass to util._refresh ---@private local function _refresh(bufnr, opts) opts = opts or {} diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index e52c06a1bd..8e014b1063 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -26,7 +26,7 @@ local function format_message_with_content_length(message) }) end ----@class vim.lsp.rpc.Headers: {string: any} +---@class (private) vim.lsp.rpc.Headers: {string: any} ---@field content_length integer --- Parses an LSP Message's header @@ -193,7 +193,9 @@ function M.rpc_response_error(code, message, data) }) end +--- Dispatchers for LSP message types. --- @class vim.lsp.rpc.Dispatchers +--- @inlinedoc --- @field notification fun(method: string, params: table) --- @field server_request fun(method: string, params: table): any?, lsp.ResponseError? --- @field on_exit fun(code: integer, signal: integer) @@ -266,8 +268,7 @@ function M.create_read_loop(handle_body, on_no_chunk, on_error) end end ----@private ----@class vim.lsp.rpc.Client +---@class (private) vim.lsp.rpc.Client ---@field message_index integer ---@field message_callbacks table dict of message_id to callback ---@field notify_reply_callbacks table dict of message_id to callback @@ -522,7 +523,7 @@ function Client:handle_body(body) end end ----@class vim.lsp.rpc.Transport +---@class (private) vim.lsp.rpc.Transport ---@field write fun(msg: string) ---@field is_closing fun(): boolean ---@field terminate fun() @@ -721,32 +722,21 @@ function M.domain_socket_connect(pipe_path) end end ----@class vim.lsp.rpc.ExtraSpawnParams ----@field cwd? string Working directory for the LSP server process ----@field detached? boolean Detach the LSP server process from the current process ----@field env? table Additional environment variables for LSP server process. See |vim.system| +--- Additional context for the LSP server process. +--- @class vim.lsp.rpc.ExtraSpawnParams +--- @inlinedoc +--- @field cwd? string Working directory for the LSP server process +--- @field detached? boolean Detach the LSP server process from the current process +--- @field env? table Additional environment variables for LSP server process. See |vim.system()| --- Starts an LSP server process and create an LSP RPC client object to --- interact with it. Communication with the spawned process happens via stdio. For --- communication via TCP, spawn a process manually and use |vim.lsp.rpc.connect()| --- ----@param cmd string[] Command to start the LSP server. ---- ----@param dispatchers? vim.lsp.rpc.Dispatchers Dispatchers for LSP message types. ---- Valid dispatcher names are: ---- - `"notification"` ---- - `"server_request"` ---- - `"on_error"` ---- - `"on_exit"` ---- ----@param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams Additional context for the LSP ---- server process. May contain: ---- - {cwd} (string) Working directory for the LSP server process ---- - {detached?} (boolean) Detach the LSP server process from the current process. ---- Defaults to false on Windows and true otherwise. ---- - {env?} (table) Additional environment variables for LSP server process ---- ----@return vim.lsp.rpc.PublicClient? Client RPC object, with these methods: +--- @param cmd string[] Command to start the LSP server. +--- @param dispatchers? vim.lsp.rpc.Dispatchers +--- @param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams +--- @return vim.lsp.rpc.PublicClient? : Client RPC object, with these methods: --- - `notify()` |vim.lsp.rpc.notify()| --- - `request()` |vim.lsp.rpc.request()| --- - `is_closing()` returns a boolean indicating if the RPC is closing. diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index fe8638bdfa..92546e8520 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -4,7 +4,7 @@ local ms = require('vim.lsp.protocol').Methods local util = require('vim.lsp.util') local uv = vim.uv ---- @class STTokenRange +--- @class (private) STTokenRange --- @field line integer line number 0-based --- @field start_col integer start column 0-based --- @field end_col integer end column 0-based @@ -12,23 +12,23 @@ local uv = vim.uv --- @field modifiers table token modifiers as a set. E.g., { static = true, readonly = true } --- @field marked boolean whether this token has had extmarks applied --- ---- @class STCurrentResult +--- @class (private) STCurrentResult --- @field version? integer document version associated with this result --- @field result_id? string resultId from the server; used with delta requests --- @field highlights? STTokenRange[] cache of highlight ranges for this document version --- @field tokens? integer[] raw token array as received by the server. used for calculating delta responses --- @field namespace_cleared? boolean whether the namespace was cleared for this result yet --- ---- @class STActiveRequest +--- @class (private) STActiveRequest --- @field request_id? integer the LSP request ID of the most recent request sent to the server --- @field version? integer the document version associated with the most recent request --- ---- @class STClientState +--- @class (private) STClientState --- @field namespace integer --- @field active_request STActiveRequest --- @field current_result STCurrentResult ----@class STHighlighter +---@class (private) STHighlighter ---@field active table ---@field bufnr integer ---@field augroup integer augroup for buffer events @@ -92,7 +92,7 @@ end --- ---@param data integer[] ---@param bufnr integer ----@param client lsp.Client +---@param client vim.lsp.Client ---@param request STActiveRequest ---@return STTokenRange[] local function tokens_to_ranges(data, bufnr, client, request) @@ -646,6 +646,7 @@ function M.stop(bufnr, client_id) end end +--- @nodoc --- @class STTokenRangeInspect : STTokenRange --- @field client_id integer @@ -727,6 +728,13 @@ function M.force_refresh(bufnr) end end +--- @class vim.lsp.semantic_tokens.highlight_token.Opts +--- @inlinedoc +--- +--- Priority for the applied extmark. +--- (Default: `vim.highlight.priorities.semantic_tokens + 3`) +--- @field priority? integer + --- Highlight a semantic token. --- --- Apply an extmark with a given highlight group for a semantic token. The @@ -735,11 +743,9 @@ end --- use inside |LspTokenUpdate| callbacks. ---@param token (table) a semantic token, found as `args.data.token` in |LspTokenUpdate|. ---@param bufnr (integer) the buffer to highlight ----@param client_id (integer) The ID of the |vim.lsp.client| +---@param client_id (integer) The ID of the |vim.lsp.Client| ---@param hl_group (string) Highlight group name ----@param opts (table|nil) Optional parameters. ---- - priority: (integer|nil) Priority for the applied extmark. Defaults ---- to `vim.highlight.priorities.semantic_tokens + 3` +---@param opts? vim.lsp.semantic_tokens.highlight_token.Opts Optional parameters: function M.highlight_token(token, bufnr, client_id, hl_group, opts) local highlighter = STHighlighter.active[bufnr] if not highlighter then diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 0553d39851..60d0f0cc83 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -675,13 +675,15 @@ local function get_bufs_with_prefix(prefix) return buffers end +--- @class vim.lsp.util.rename.Opts +--- @inlinedoc +--- @field overwrite? boolean +--- @field ignoreIfExists? boolean + --- Rename old_fname to new_fname ---- ----@param old_fname string ----@param new_fname string ----@param opts? table options ---- - overwrite? boolean ---- - ignoreIfExists? boolean +--- @param old_fname string +--- @param new_fname string +--- @param opts? vim.lsp.util.rename.Opts Options: function M.rename(old_fname, new_fname, opts) opts = opts or {} local skip = not opts.overwrite or opts.ignoreIfExists @@ -1450,7 +1452,7 @@ function M.stylize_markdown(bufnr, contents, opts) return stripped end ---- @class lsp.util.NormalizeMarkdownOptions +--- @class (private) vim.lsp.util._normalize_markdown.Opts --- @field width integer Thematic breaks are expanded to this size. Defaults to 80. --- Normalizes Markdown input to a canonical form. @@ -1466,7 +1468,7 @@ end --- ---@private ---@param contents string[] ----@param opts? lsp.util.NormalizeMarkdownOptions +---@param opts? vim.lsp.util._normalize_markdown.Opts ---@return string[] table of lines containing normalized Markdown ---@see https://github.github.com/gfm function M._normalize_markdown(contents, opts) @@ -1537,7 +1539,7 @@ local function close_preview_autocmd(events, winnr, bufnrs) end end ----@internal +---@private --- Computes size of float needed to show contents (with optional wrapping) --- ---@param contents table of lines to show in window @@ -1613,24 +1615,50 @@ function M._make_floating_popup_size(contents, opts) return width, height end +--- @class vim.lsp.util.open_floating_preview.Opts +--- @inlinedoc +--- +--- Height of floating window +--- @field height? integer +--- +--- Width of floating window +--- @field width? integer +--- +--- Wrap long lines +--- (default: `true`) +--- @field wrap? boolean +--- +--- Character to wrap at for computing height when wrap is enabled +--- @field wrap_at? integer +--- +--- Maximal width of floating window +--- @field max_width? integer +--- +--- Maximal height of floating window +--- @field max_height? integer +--- +--- If a popup with this id is opened, then focus it +--- @field focus_id? string +--- +--- List of events that closes the floating window +--- @field close_events? table +--- +--- Make float focusable. +--- (default: `true`) +--- @field focusable? boolean +--- +--- If `true`, and if {focusable} is also `true`, focus an existing floating +--- window with the same {focus_id} +--- (default: `true`) +--- @field focus? boolean + --- Shows contents in a floating window. --- ---@param contents table of lines to show in window ---@param syntax string of syntax to set for opened buffer ----@param opts table with optional fields (additional keys are filtered with |vim.lsp.util.make_floating_popup_options()| ---- before they are passed on to |nvim_open_win()|) ---- - height: (integer) height of floating window ---- - width: (integer) width of floating window ---- - wrap: (boolean, default true) wrap long lines ---- - wrap_at: (integer) character to wrap at for computing height when wrap is enabled ---- - max_width: (integer) maximal width of floating window ---- - max_height: (integer) maximal height of floating window ---- - focus_id: (string) if a popup with this id is opened, then focus it ---- - close_events: (table) list of events that closes the floating window ---- - focusable: (boolean, default true) Make float focusable ---- - focus: (boolean, default true) If `true`, and if {focusable} ---- is also `true`, focus an existing floating window with the same ---- {focus_id} +---@param opts? vim.lsp.util.open_floating_preview.Opts with optional fields +--- (additional keys are filtered with |vim.lsp.util.make_floating_popup_options()| +--- before they are passed on to |nvim_open_win()|) ---@return integer bufnr of newly created float window ---@return integer winid of newly created float window preview window function M.open_floating_preview(contents, syntax, opts) @@ -1794,7 +1822,8 @@ local position_sort = sort_by_key(function(v) return { v.start.line, v.start.character } end) ----@class vim.lsp.util.LocationItem +---@class vim.lsp.util.locations_to_items.ret +---@inlinedoc ---@field filename string ---@field lnum integer 1-indexed line number ---@field col integer 1-indexed column @@ -1813,7 +1842,7 @@ end) ---@param locations lsp.Location[]|lsp.LocationLink[] ---@param offset_encoding string offset_encoding for locations utf-8|utf-16|utf-32 --- default to first client of buffer ----@return vim.lsp.util.LocationItem[] list of items +---@return vim.lsp.util.locations_to_items.ret[] function M.locations_to_items(locations, offset_encoding) if offset_encoding == nil then vim.notify_once( @@ -2221,16 +2250,16 @@ local function make_line_range_params(bufnr, start_line, end_line, offset_encodi } end ----@private ---- Request updated LSP information for a buffer. ---- ----@class lsp.util.RefreshOptions +---@class (private) vim.lsp.util._refresh.Opts ---@field bufnr integer? Buffer to refresh (default: 0) ---@field only_visible? boolean Whether to only refresh for the visible regions of the buffer (default: false) ---@field client_id? integer Client ID to refresh (default: all clients) --- + +---@private +--- Request updated LSP information for a buffer. +--- ---@param method string LSP method to call ----@param opts? lsp.util.RefreshOptions Options table +---@param opts? vim.lsp.util._refresh.Opts Options table function M._refresh(method, opts) opts = opts or {} local bufnr = opts.bufnr diff --git a/runtime/lua/vim/secure.lua b/runtime/lua/vim/secure.lua index d29c356af3..3992eef78a 100644 --- a/runtime/lua/vim/secure.lua +++ b/runtime/lua/vim/secure.lua @@ -108,22 +108,25 @@ function M.read(path) return contents end ----@class vim.trust.opts ----@field action string ----@field path? string ----@field bufnr? integer +--- @class vim.trust.opts +--- @inlinedoc +--- +--- - `'allow'` to add a file to the trust database and trust it, +--- - `'deny'` to add a file to the trust database and deny it, +--- - `'remove'` to remove file from the trust database +--- @field action 'allow'|'deny'|'remove' +--- +--- Path to a file to update. Mutually exclusive with {bufnr}. +--- Cannot be used when {action} is "allow". +--- @field path? string +--- Buffer number to update. Mutually exclusive with {path}. +--- @field bufnr? integer --- Manage the trust database. --- --- The trust database is located at |$XDG_STATE_HOME|/nvim/trust. --- ----@param opts (table): ---- - action (string): "allow" to add a file to the trust database and trust it, ---- "deny" to add a file to the trust database and deny it, ---- "remove" to remove file from the trust database ---- - path (string|nil): Path to a file to update. Mutually exclusive with {bufnr}. ---- Cannot be used when {action} is "allow". ---- - bufnr (number|nil): Buffer number to update. Mutually exclusive with {path}. +---@param opts? vim.trust.opts ---@return boolean success true if operation was successful ---@return string msg full path if operation was successful, else error message function M.trust(opts) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 83fdfede89..ec70630df3 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -65,8 +65,13 @@ function vim.deepcopy(orig, noref) end --- @class vim.gsplit.Opts ---- @field plain? boolean Use `sep` literally (as in string.find). ---- @field trimempty? boolean Discard empty segments at start and end of the sequence. +--- @inlinedoc +--- +--- Use `sep` literally (as in string.find). +--- @field plain? boolean +--- +--- Discard empty segments at start and end of the sequence. +--- @field trimempty? boolean --- Gets an |iterator| that splits a string at each instance of a separator, in "lazy" fashion --- (as opposed to |vim.split()| which is "eager"). @@ -96,10 +101,8 @@ end --- --- @param s string String to split --- @param sep string Separator or pattern ---- @param opts? vim.gsplit.Opts (table) Keyword arguments |kwargs|: ---- - plain: (boolean) Use `sep` literally (as in string.find). ---- - trimempty: (boolean) Discard empty segments at start and end of the sequence. ----@return fun():string|nil (function) Iterator over the split components +--- @param opts? vim.gsplit.Opts Keyword arguments |kwargs|: +--- @return fun():string|nil (function) Iterator over the split components function vim.gsplit(s, sep, opts) local plain --- @type boolean? local trimempty = false @@ -192,7 +195,7 @@ end --- ---@param s string String to split ---@param sep string Separator or pattern ----@param opts? table Keyword arguments |kwargs| accepted by |vim.gsplit()| +---@param opts? vim.gsplit.Opts Keyword arguments |kwargs|: ---@return string[] : List of split components function vim.split(s, sep, opts) local t = {} @@ -276,6 +279,9 @@ function vim.tbl_filter(func, t) end --- @class vim.tbl_contains.Opts +--- @inlinedoc +--- +--- `value` is a function reference to be checked (default false) --- @field predicate? boolean --- Checks if a table contains a given value, specified either directly or via @@ -294,8 +300,7 @@ end --- ---@param t table Table to check ---@param value any Value to compare or predicate function reference ----@param opts? vim.tbl_contains.Opts (table) Keyword arguments |kwargs|: ---- - predicate: (boolean) `value` is a function reference to be checked (default false) +---@param opts? vim.tbl_contains.Opts Keyword arguments |kwargs|: ---@return boolean `true` if `t` contains `value` function vim.tbl_contains(t, value, opts) vim.validate({ t = { t, 't' }, opts = { opts, 't', true } }) @@ -764,6 +769,7 @@ do ['userdata'] = 'userdata', } + --- @nodoc --- @class vim.validate.Spec {[1]: any, [2]: string|string[], [3]: boolean } --- @field [1] any Argument value --- @field [2] string|string[]|fun(v:any):boolean, string? Type name, or callable diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua index 09b7576d97..5e60efa778 100644 --- a/runtime/lua/vim/snippet.lua +++ b/runtime/lua/vim/snippet.lua @@ -101,7 +101,7 @@ local function get_extmark_range(bufnr, extmark_id) return { mark[1], mark[2], mark[3].end_row, mark[3].end_col } end ---- @class vim.snippet.Tabstop +--- @class (private) vim.snippet.Tabstop --- @field extmark_id integer --- @field bufnr integer --- @field index integer @@ -177,7 +177,7 @@ function Tabstop:set_right_gravity(right_gravity) }) end ---- @class vim.snippet.Session +--- @class (private) vim.snippet.Session --- @field bufnr integer --- @field extmark_id integer --- @field tabstops table diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 9b69f95f54..61c5d66958 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -1,6 +1,6 @@ local api = vim.api ----@type table +---@type table local parsers = setmetatable({}, { __mode = 'v' }) local M = vim._defer_require('vim.treesitter', { @@ -30,7 +30,7 @@ M.minimum_language_version = vim._ts_get_minimum_language_version() ---@param lang string Language of the parser ---@param opts (table|nil) Options to pass to the created language tree --- ----@return LanguageTree object to use for parsing +---@return vim.treesitter.LanguageTree object to use for parsing function M._create_parser(bufnr, lang, opts) if bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() @@ -80,7 +80,7 @@ end ---@param lang (string|nil) Filetype of this parser (default: buffer filetype) ---@param opts (table|nil) Options to pass to the created language tree --- ----@return LanguageTree object to use for parsing +---@return vim.treesitter.LanguageTree object to use for parsing function M.get_parser(bufnr, lang, opts) opts = opts or {} @@ -119,7 +119,7 @@ end ---@param lang string Language of this string ---@param opts (table|nil) Options to pass to the created language tree --- ----@return LanguageTree object to use for parsing +---@return vim.treesitter.LanguageTree object to use for parsing function M.get_string_parser(str, lang, opts) vim.validate({ str = { str, 'string' }, @@ -172,7 +172,7 @@ end ---to get the range with directives applied. ---@param node TSNode ---@param source integer|string|nil Buffer or string from which the {node} is extracted ----@param metadata TSMetadata|nil +---@param metadata vim.treesitter.query.TSMetadata|nil ---@return Range6 function M.get_range(node, source, metadata) if metadata and metadata.range then @@ -326,10 +326,21 @@ function M.get_captures_at_cursor(winnr) return captures end ---- @class vim.treesitter.GetNodeOpts +--- Optional keyword arguments: +--- @class vim.treesitter.get_node.Opts +--- @inlinedoc +--- +--- Buffer number (nil or 0 for current buffer) --- @field bufnr integer? +--- +--- 0-indexed (row, col) tuple. Defaults to cursor position in the +--- current window. Required if {bufnr} is not the current buffer --- @field pos { [1]: integer, [2]: integer }? +--- +--- Parser language. (default: from buffer filetype) --- @field lang string? +--- +--- Ignore injected languages (default true) --- @field ignore_injections boolean? --- Returns the smallest named node at the given position @@ -342,12 +353,7 @@ end --- vim.treesitter.get_parser(bufnr):parse(range) --- ``` --- ----@param opts vim.treesitter.GetNodeOpts? Optional keyword arguments: ---- - bufnr integer|nil Buffer number (nil or 0 for current buffer) ---- - pos table|nil 0-indexed (row, col) tuple. Defaults to cursor position in the ---- current window. Required if {bufnr} is not the current buffer ---- - lang string|nil Parser language. (default: from buffer filetype) ---- - ignore_injections boolean Ignore injected languages (default true) +---@param opts vim.treesitter.get_node.Opts? --- ---@return TSNode | nil Node at the given position function M.get_node(opts) diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua index 6ec997eb4a..b91e8ac38d 100644 --- a/runtime/lua/vim/treesitter/_query_linter.lua +++ b/runtime/lua/vim/treesitter/_query_linter.lua @@ -45,7 +45,7 @@ local function guess_query_lang(buf) end --- @param buf integer ---- @param opts QueryLinterOpts|QueryLinterNormalizedOpts|nil +--- @param opts vim.treesitter.query.lint.Opts|QueryLinterNormalizedOpts|nil --- @return QueryLinterNormalizedOpts local function normalize_opts(buf, opts) opts = opts or {} @@ -122,7 +122,7 @@ local parse = vim.func._memoize(hash_parse, function(node, buf, lang) end) --- @param buf integer ---- @param match TSMatch +--- @param match vim.treesitter.query.TSMatch --- @param query Query --- @param lang_context QueryLinterLanguageContext --- @param diagnostics Diagnostic[] @@ -153,7 +153,7 @@ end --- @private --- @param buf integer Buffer to lint ---- @param opts QueryLinterOpts|QueryLinterNormalizedOpts|nil Options for linting +--- @param opts vim.treesitter.query.lint.Opts|QueryLinterNormalizedOpts|nil Options for linting function M.lint(buf, opts) if buf == 0 then buf = api.nvim_get_current_buf() diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 4c8f6e466f..dc2a14d238 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -1,23 +1,21 @@ local api = vim.api ----@class TSDevModule local M = {} ----@private ----@class TSTreeView +---@class (private) vim.treesitter.dev.TSTreeView ---@field ns integer API namespace ----@field opts TSTreeViewOpts ----@field nodes TSP.Node[] ----@field named TSP.Node[] +---@field opts vim.treesitter.dev.TSTreeViewOpts +---@field nodes vim.treesitter.dev.Node[] +---@field named vim.treesitter.dev.Node[] local TSTreeView = {} ---@private ----@class TSTreeViewOpts +---@class (private) vim.treesitter.dev.TSTreeViewOpts ---@field anon boolean If true, display anonymous nodes. ---@field lang boolean If true, display the language alongside each node. ---@field indent number Number of spaces to indent nested lines. ----@class TSP.Node +---@class (private) vim.treesitter.dev.Node ---@field node TSNode Treesitter node ---@field field string? Node field ---@field depth integer Depth of this node in the tree @@ -25,7 +23,7 @@ local TSTreeView = {} --- inspector is drawn. ---@field lang string Source language of this node ----@class TSP.Injection +---@class (private) vim.treesitter.dev.Injection ---@field lang string Source language of this injection ---@field root TSNode Root node of the injection @@ -45,9 +43,9 @@ local TSTreeView = {} ---@param depth integer Current recursion depth ---@param field string|nil The field of the current node ---@param lang string Language of the tree currently being traversed ----@param injections table Mapping of node ids to root nodes +---@param injections table Mapping of node ids to root nodes --- of injected language trees (see explanation above) ----@param tree TSP.Node[] Output table containing a list of tables each representing a node in the tree +---@param tree vim.treesitter.dev.Node[] Output table containing a list of tables each representing a node in the tree local function traverse(node, depth, field, lang, injections, tree) table.insert(tree, { node = node, @@ -73,7 +71,7 @@ end ---@param bufnr integer Source buffer number ---@param lang string|nil Language of source buffer --- ----@return TSTreeView|nil +---@return vim.treesitter.dev.TSTreeView|nil ---@return string|nil Error message, if any --- ---@package @@ -88,7 +86,7 @@ function TSTreeView:new(bufnr, lang) -- the primary tree that contains that root. Add a mapping from the node in the primary tree to -- the root in the child tree to the {injections} table. local root = parser:parse(true)[1]:root() - local injections = {} ---@type table + local injections = {} ---@type table parser:for_each_tree(function(parent_tree, parent_ltree) local parent = parent_tree:root() @@ -109,7 +107,7 @@ function TSTreeView:new(bufnr, lang) local nodes = traverse(root, 0, nil, parser:lang(), injections, {}) - local named = {} ---@type TSP.Node[] + local named = {} ---@type vim.treesitter.dev.Node[] for _, v in ipairs(nodes) do if v.node:named() then named[#named + 1] = v @@ -120,7 +118,7 @@ function TSTreeView:new(bufnr, lang) ns = api.nvim_create_namespace('treesitter/dev-inspect'), nodes = nodes, named = named, - ---@type TSTreeViewOpts + ---@type vim.treesitter.dev.TSTreeViewOpts opts = { anon = false, lang = false, @@ -171,7 +169,7 @@ end --- Updates the cursor position in the inspector to match the node under the cursor. --- ---- @param treeview TSTreeView +--- @param treeview vim.treesitter.dev.TSTreeView --- @param lang string --- @param source_buf integer --- @param inspect_buf integer @@ -278,7 +276,7 @@ end --- The node number is dependent on whether or not anonymous nodes are displayed. --- ---@param i integer Node number to get ----@return TSP.Node +---@return vim.treesitter.dev.Node ---@package function TSTreeView:get(i) local t = self.opts.anon and self.nodes or self.named @@ -287,7 +285,7 @@ end --- Iterate over all of the nodes in this View. --- ----@return (fun(): integer, TSP.Node) Iterator over all nodes in this View +---@return (fun(): integer, vim.treesitter.dev.Node) Iterator over all nodes in this View ---@return table ---@return integer ---@package @@ -295,22 +293,31 @@ function TSTreeView:iter() return ipairs(self.opts.anon and self.nodes or self.named) end ---- @class InspectTreeOpts ---- @field lang string? The language of the source buffer. If omitted, the ---- filetype of the source buffer is used. ---- @field bufnr integer? Buffer to draw the tree into. If omitted, a new ---- buffer is created. ---- @field winid integer? Window id to display the tree buffer in. If omitted, ---- a new window is created with {command}. ---- @field command string? Vimscript command to create the window. Default ---- value is "60vnew". Only used when {winid} is nil. ---- @field title (string|fun(bufnr:integer):string|nil) Title of the window. If a ---- function, it accepts the buffer number of the source ---- buffer as its only argument and should return a string. +--- @class vim.treesitter.dev.inspect_tree.Opts +--- @inlinedoc +--- +--- The language of the source buffer. If omitted, the filetype of the source +--- buffer is used. +--- @field lang string? +--- +--- Buffer to draw the tree into. If omitted, a new buffer is created. +--- @field bufnr integer? +--- +--- Window id to display the tree buffer in. If omitted, a new window is +--- created with {command}. +--- @field winid integer? +--- +--- Vimscript command to create the window. Default value is "60vnew". +--- Only used when {winid} is nil. +--- @field command string? +--- +--- Title of the window. If a function, it accepts the buffer number of the +--- source buffer as its only argument and should return a string. +--- @field title (string|fun(bufnr:integer):string|nil) --- @private --- ---- @param opts InspectTreeOpts? +--- @param opts vim.treesitter.dev.inspect_tree.Opts? function M.inspect_tree(opts) vim.validate({ opts = { opts, 't', true }, diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 8fb591bc46..388680259a 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -4,9 +4,9 @@ local Range = require('vim.treesitter._range') local ns = api.nvim_create_namespace('treesitter/highlighter') ----@alias vim.treesitter.highlighter.Iter fun(end_line: integer|nil): integer, TSNode, TSMetadata +---@alias vim.treesitter.highlighter.Iter fun(end_line: integer|nil): integer, TSNode, vim.treesitter.query.TSMetadata ----@class vim.treesitter.highlighter.Query +---@class (private) vim.treesitter.highlighter.Query ---@field private _query vim.treesitter.Query? ---@field private lang string ---@field private hl_cache table @@ -52,22 +52,23 @@ function TSHighlighterQuery:query() return self._query end ----@class vim.treesitter.highlighter.State +---@class (private) vim.treesitter.highlighter.State ---@field tstree TSTree ---@field next_row integer ---@field iter vim.treesitter.highlighter.Iter? ---@field highlighter_query vim.treesitter.highlighter.Query +---@nodoc ---@class vim.treesitter.highlighter ---@field active table ---@field bufnr integer ----@field orig_spelloptions string +---@field private orig_spelloptions string --- A map of highlight states. --- This state is kept during rendering across each line update. ----@field _highlight_states vim.treesitter.highlighter.State[] ----@field _queries table ----@field tree LanguageTree ----@field redraw_count integer +---@field private _highlight_states vim.treesitter.highlighter.State[] +---@field private _queries table +---@field tree vim.treesitter.LanguageTree +---@field private redraw_count integer local TSHighlighter = { active = {}, } @@ -78,7 +79,7 @@ TSHighlighter.__index = TSHighlighter --- --- Creates a highlighter for `tree`. --- ----@param tree LanguageTree parser object to use for highlighting +---@param tree vim.treesitter.LanguageTree parser object to use for highlighting ---@param opts (table|nil) Configuration of the highlighter: --- - queries table overwrite queries used by the highlighter ---@return vim.treesitter.highlighter Created highlighter object diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 0f6d5ecbd0..78c73c698c 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -56,10 +56,17 @@ function M.require_language(lang, path, silent, symbol_name) return true end ----@class vim.treesitter.language.RequireLangOpts ----@field path? string ----@field silent? boolean +---@class vim.treesitter.language.add.Opts +---@inlinedoc +--- +---Default filetype the parser should be associated with. +---(Default: {lang}) ---@field filetype? string|string[] +--- +---Optional path the parser is located at +---@field path? string +--- +---Internal symbol name for the language to load ---@field symbol_name? string --- Load parser with name {lang} @@ -67,13 +74,8 @@ end --- Parsers are searched in the `parser` runtime directory, or the provided {path} --- ---@param lang string Name of the parser (alphanumerical and `_` only) ----@param opts (table|nil) Options: ---- - filetype (string|string[]) Default filetype the parser should be associated with. ---- Defaults to {lang}. ---- - path (string|nil) Optional path the parser is located at ---- - symbol_name (string|nil) Internal symbol name for the language to load +---@param opts? vim.treesitter.language.add.Opts Options: function M.add(lang, opts) - ---@cast opts vim.treesitter.language.RequireLangOpts opts = opts or {} local path = opts.path local filetype = opts.filetype or lang diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index d01da8be71..2f1aa36d18 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -67,10 +67,11 @@ local TSCallbackNames = { on_child_removed = 'child_removed', } ----@class LanguageTree +---@nodoc +---@class vim.treesitter.LanguageTree ---@field private _callbacks table Callback handlers ---@field package _callbacks_rec table Callback handlers (recursive) ----@field private _children table Injected languages +---@field private _children table Injected languages ---@field private _injection_query Query Queries defining injected languages ---@field private _injections_processed boolean ---@field private _opts table Options @@ -89,7 +90,9 @@ local TSCallbackNames = { ---@field private _logfile? file* local LanguageTree = {} ----@class LanguageTreeOpts +---Optional arguments: +---@class vim.treesitter.LanguageTree.new.Opts +---@inlinedoc ---@field queries table -- Deprecated ---@field injections table @@ -102,14 +105,11 @@ LanguageTree.__index = LanguageTree --- ---@param source (integer|string) Buffer or text string to parse ---@param lang string Root language of this tree ----@param opts (table|nil) Optional arguments: ---- - injections table Map of language to injection query strings. Overrides the ---- built-in runtime file searching for language injections. +---@param opts vim.treesitter.LanguageTree.new.Opts? ---@param parent_lang? string Parent language name of this tree ----@return LanguageTree parser object +---@return vim.treesitter.LanguageTree parser object function LanguageTree.new(source, lang, opts, parent_lang) language.add(lang) - ---@type LanguageTreeOpts opts = opts or {} if source == 0 then @@ -118,7 +118,7 @@ function LanguageTree.new(source, lang, opts, parent_lang) local injections = opts.injections or {} - --- @type LanguageTree + --- @type vim.treesitter.LanguageTree local self = { _source = source, _lang = lang, @@ -194,7 +194,7 @@ local function tcall(f, ...) end ---@private ----@vararg any +---@param ... any function LanguageTree:_log(...) if not self._logger then return @@ -464,7 +464,7 @@ end --- add recursion yourself if needed. --- Invokes the callback for each |LanguageTree| and its children recursively --- ----@param fn fun(tree: LanguageTree, lang: string) +---@param fn fun(tree: vim.treesitter.LanguageTree, lang: string) ---@param include_self boolean|nil Whether to include the invoking tree in the results function LanguageTree:for_each_child(fn, include_self) vim.deprecate('LanguageTree:for_each_child()', 'LanguageTree:children()', '0.11') @@ -481,7 +481,7 @@ end --- --- Note: This includes the invoking tree's child trees as well. --- ----@param fn fun(tree: TSTree, ltree: LanguageTree) +---@param fn fun(tree: TSTree, ltree: vim.treesitter.LanguageTree) function LanguageTree:for_each_tree(fn) for _, tree in pairs(self._trees) do fn(tree, self) @@ -498,7 +498,7 @@ end --- ---@private ---@param lang string Language to add. ----@return LanguageTree injected +---@return vim.treesitter.LanguageTree injected function LanguageTree:add_child(lang) if self._children[lang] then self:remove_child(lang) @@ -668,7 +668,7 @@ end ---@param node TSNode ---@param source string|integer ----@param metadata TSMetadata +---@param metadata vim.treesitter.query.TSMetadata ---@param include_children boolean ---@return Range6[] local function get_node_ranges(node, source, metadata, include_children) @@ -702,13 +702,14 @@ local function get_node_ranges(node, source, metadata, include_children) return ranges end ----@class TSInjectionElem +---@nodoc +---@class vim.treesitter.languagetree.InjectionElem ---@field combined boolean ---@field regions Range6[][] ----@alias TSInjection table> +---@alias vim.treesitter.languagetree.Injection table> ----@param t table +---@param t table ---@param tree_index integer ---@param pattern integer ---@param lang string @@ -783,7 +784,7 @@ end --- Extract injections according to: --- https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection ---@param match table ----@param metadata TSMetadata +---@param metadata vim.treesitter.query.TSMetadata ---@return string?, boolean, Range6[] function LanguageTree:_get_injection(match, metadata) local ranges = {} ---@type Range6[] @@ -836,7 +837,7 @@ function LanguageTree:_get_injections() return {} end - ---@type table + ---@type table local injections = {} for index, tree in pairs(self._trees) do @@ -1150,7 +1151,7 @@ end --- Gets the appropriate language that contains {range}. --- ---@param range Range4 `{ start_line, start_col, end_line, end_col }` ----@return LanguageTree Managing {range} +---@return vim.treesitter.LanguageTree Managing {range} function LanguageTree:language_for_range(range) for _, child in pairs(self._children) do if child:contains(range) then diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 57272dbd60..6c7f713fd7 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -3,6 +3,7 @@ local language = require('vim.treesitter.language') local M = {} +---@nodoc ---Parsed query, see |vim.treesitter.query.parse()| --- ---@class vim.treesitter.Query @@ -31,6 +32,7 @@ function Query.new(lang, ts_query) return self end +---@nodoc ---Information for Query, see |vim.treesitter.query.parse()| ---@class vim.treesitter.QueryInfo --- @@ -296,7 +298,7 @@ end --- handling the "any" vs "all" semantics. They are called from the --- predicate_handlers table with the appropriate arguments for each predicate. local impl = { - --- @param match TSMatch + --- @param match vim.treesitter.query.TSMatch --- @param source integer|string --- @param predicate any[] --- @param any boolean @@ -331,7 +333,7 @@ local impl = { return not any end, - --- @param match TSMatch + --- @param match vim.treesitter.query.TSMatch --- @param source integer|string --- @param predicate any[] --- @param any boolean @@ -371,7 +373,7 @@ local impl = { end, }) - --- @param match TSMatch + --- @param match vim.treesitter.query.TSMatch --- @param source integer|string --- @param predicate any[] --- @param any boolean @@ -394,7 +396,7 @@ local impl = { end end)(), - --- @param match TSMatch + --- @param match vim.treesitter.query.TSMatch --- @param source integer|string --- @param predicate any[] --- @param any boolean @@ -421,12 +423,13 @@ local impl = { end, } ----@class TSMatch +---@nodoc +---@class vim.treesitter.query.TSMatch ---@field pattern? integer ---@field active? boolean ---@field [integer] TSNode[] ----@alias TSPredicate fun(match: TSMatch, pattern: integer, source: integer|string, predicate: any[]): boolean +---@alias TSPredicate fun(match: vim.treesitter.query.TSMatch, pattern: integer, source: integer|string, predicate: any[]): boolean -- Predicate handler receive the following arguments -- (match, pattern, bufnr, predicate) @@ -534,13 +537,14 @@ local predicate_handlers = { predicate_handlers['vim-match?'] = predicate_handlers['match?'] predicate_handlers['any-vim-match?'] = predicate_handlers['any-match?'] ----@class TSMetadata +---@nodoc +---@class vim.treesitter.query.TSMetadata ---@field range? Range ---@field conceal? string ----@field [integer] TSMetadata +---@field [integer] vim.treesitter.query.TSMetadata ---@field [string] integer|string ----@alias TSDirective fun(match: TSMatch, _, _, predicate: (string|integer)[], metadata: TSMetadata) +---@alias TSDirective fun(match: vim.treesitter.query.TSMatch, _, _, predicate: (string|integer)[], metadata: vim.treesitter.query.TSMetadata) -- Predicate handler receive the following arguments -- (match, pattern, bufnr, predicate) @@ -767,7 +771,7 @@ local function is_directive(name) end ---@private ----@param match TSMatch +---@param match vim.treesitter.query.TSMatch ---@param pattern integer ---@param source integer|string function Query:match_preds(match, pattern, source) @@ -806,8 +810,8 @@ function Query:match_preds(match, pattern, source) end ---@private ----@param match TSMatch ----@param metadata TSMetadata +---@param match vim.treesitter.query.TSMatch +---@param metadata vim.treesitter.query.TSMetadata function Query:apply_directives(match, pattern, source, metadata) local preds = self.info.patterns[pattern] @@ -871,7 +875,7 @@ end ---@param start? integer Starting line for the search. Defaults to `node:start()`. ---@param stop? integer Stopping line for the search (end-exclusive). Defaults to `node:end_()`. --- ----@return (fun(end_line: integer|nil): integer, TSNode, TSMetadata): +---@return (fun(end_line: integer|nil): integer, TSNode, vim.treesitter.query.TSMetadata): --- capture id, capture node, metadata function Query:iter_captures(node, source, start, stop) if type(source) == 'number' and source == 0 then @@ -880,7 +884,7 @@ function Query:iter_captures(node, source, start, stop) start, stop = value_or_node_range(start, stop, node) - local raw_iter = node:_rawquery(self.query, true, start, stop) ---@type fun(): integer, TSNode, TSMatch + local raw_iter = node:_rawquery(self.query, true, start, stop) ---@type fun(): integer, TSNode, vim.treesitter.query.TSMatch local function iter(end_line) local capture, captured_node, match = raw_iter() local metadata = {} @@ -952,7 +956,7 @@ function Query:iter_matches(node, source, start, stop, opts) start, stop = value_or_node_range(start, stop, node) - local raw_iter = node:_rawquery(self.query, false, start, stop, opts) ---@type fun(): integer, TSMatch + local raw_iter = node:_rawquery(self.query, false, start, stop, opts) ---@type fun(): integer, vim.treesitter.query.TSMatch local function iter() local pattern, match = raw_iter() local metadata = {} @@ -982,9 +986,16 @@ function Query:iter_matches(node, source, start, stop, opts) return iter end ----@class QueryLinterOpts ----@field langs (string|string[]|nil) ----@field clear (boolean) +--- Optional keyword arguments: +--- @class vim.treesitter.query.lint.Opts +--- @inlinedoc +--- +--- Language(s) to use for checking the query. +--- If multiple languages are specified, queries are validated for all of them +--- @field langs? string|string[] +--- +--- Just clear current lint errors +--- @field clear boolean --- Lint treesitter queries using installed parser, or clear lint errors. --- @@ -999,10 +1010,7 @@ end --- of the query file, e.g., if the path ends in `/lua/highlights.scm`, the parser for the --- `lua` language will be used. ---@param buf (integer) Buffer handle ----@param opts? QueryLinterOpts (table) Optional keyword arguments: ---- - langs (string|string[]|nil) Language(s) to use for checking the query. ---- If multiple languages are specified, queries are validated for all of them ---- - clear (boolean) if `true`, just clear current lint errors +---@param opts? vim.treesitter.query.lint.Opts function M.lint(buf, opts) if opts and opts.clear then vim.treesitter._query_linter.clear(buf) diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua index 09a6fa825b..f97e81273e 100644 --- a/runtime/lua/vim/version.lua +++ b/runtime/lua/vim/version.lua @@ -54,7 +54,8 @@ local M = {} ----@class Version +---@nodoc +---@class vim.Version ---@field [1] number ---@field [2] number ---@field [3] number @@ -111,7 +112,7 @@ function Version:__newindex(key, value) end end ----@param other Version +---@param other vim.Version function Version:__eq(other) for i = 1, 3 do if self[i] ~= other[i] then @@ -132,7 +133,7 @@ function Version:__tostring() return ret end ----@param other Version +---@param other vim.Version function Version:__lt(other) for i = 1, 3 do if self[i] > other[i] then @@ -144,7 +145,7 @@ function Version:__lt(other) return -1 == cmp_prerel(self.prerelease, other.prerelease) end ----@param other Version +---@param other vim.Version function Version:__le(other) return self < other or self == other end @@ -153,9 +154,9 @@ end --- --- Creates a new Version object, or returns `nil` if `version` is invalid. --- ---- @param version string|number[]|Version +--- @param version string|number[]|vim.Version --- @param strict? boolean Reject "1.0", "0-x", "3.2a" or other non-conforming version strings ---- @return Version? +--- @return vim.Version? function M._version(version, strict) -- Adapted from https://github.com/folke/lazy.nvim if type(version) == 'table' then if version.major then @@ -203,7 +204,7 @@ end ---TODO: generalize this, move to func.lua --- ----@generic T: Version +---@generic T: vim.Version ---@param versions T[] ---@return T? function M.last(versions) @@ -216,14 +217,15 @@ function M.last(versions) return last end ----@class VersionRange ----@field from Version ----@field to? Version +---@class vim.VersionRange +---@inlinedoc +---@field from vim.Version +---@field to? vim.Version local VersionRange = {} --- @private --- ----@param version string|Version +---@param version string|vim.Version function VersionRange:has(version) if type(version) == 'string' then ---@diagnostic disable-next-line: cast-local-type @@ -272,6 +274,7 @@ end --- @see # https://github.com/npm/node-semver#ranges --- --- @param spec string Version range "spec" +--- @return vim.VersionRange function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim if spec == '*' or spec == '' then return setmetatable({ from = M.parse('0.0.0') }, { __index = VersionRange }) @@ -300,8 +303,8 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim local semver = M.parse(version) if semver then - local from = semver --- @type Version? - local to = vim.deepcopy(semver, true) --- @type Version? + local from = semver --- @type vim.Version? + local to = vim.deepcopy(semver, true) --- @type vim.Version? ---@diagnostic disable: need-check-nil if mods == '' or mods == '=' then to.patch = to.patch + 1 @@ -340,7 +343,7 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim end end ----@param v string|Version +---@param v string|vim.Version ---@return string local function create_err_msg(v) if type(v) == 'string' then @@ -369,8 +372,8 @@ end --- --- @note Per semver, build metadata is ignored when comparing two otherwise-equivalent versions. --- ----@param v1 Version|number[]|string Version object. ----@param v2 Version|number[]|string Version to compare with `v1`. +---@param v1 vim.Version|number[]|string Version object. +---@param v2 vim.Version|number[]|string Version to compare with `v1`. ---@return integer -1 if `v1 < v2`, 0 if `v1 == v2`, 1 if `v1 > v2`. function M.cmp(v1, v2) local v1_parsed = assert(M._version(v1), create_err_msg(v1)) @@ -385,40 +388,40 @@ function M.cmp(v1, v2) end ---Returns `true` if the given versions are equal. See |vim.version.cmp()| for usage. ----@param v1 Version|number[]|string ----@param v2 Version|number[]|string +---@param v1 vim.Version|number[]|string +---@param v2 vim.Version|number[]|string ---@return boolean function M.eq(v1, v2) return M.cmp(v1, v2) == 0 end ---Returns `true` if `v1 <= v2`. See |vim.version.cmp()| for usage. ----@param v1 Version|number[]|string ----@param v2 Version|number[]|string +---@param v1 vim.Version|number[]|string +---@param v2 vim.Version|number[]|string ---@return boolean function M.le(v1, v2) return M.cmp(v1, v2) <= 0 end ---Returns `true` if `v1 < v2`. See |vim.version.cmp()| for usage. ----@param v1 Version|number[]|string ----@param v2 Version|number[]|string +---@param v1 vim.Version|number[]|string +---@param v2 vim.Version|number[]|string ---@return boolean function M.lt(v1, v2) return M.cmp(v1, v2) == -1 end ---Returns `true` if `v1 >= v2`. See |vim.version.cmp()| for usage. ----@param v1 Version|number[]|string ----@param v2 Version|number[]|string +---@param v1 vim.Version|number[]|string +---@param v2 vim.Version|number[]|string ---@return boolean function M.ge(v1, v2) return M.cmp(v1, v2) >= 0 end ---Returns `true` if `v1 > v2`. See |vim.version.cmp()| for usage. ----@param v1 Version|number[]|string ----@param v2 Version|number[]|string +---@param v1 vim.Version|number[]|string +---@param v2 vim.Version|number[]|string ---@return boolean function M.gt(v1, v2) return M.cmp(v1, v2) == 1 @@ -438,7 +441,7 @@ end --- - strict (boolean): Default false. If `true`, no coercion is attempted on --- input not conforming to semver v2.0.0. If `false`, `parse()` attempts to --- coerce input such as "1.0", "0-x", "tmux 3.2a" into valid versions. ----@return Version? parsed_version Version object or `nil` if input is invalid. +---@return vim.Version? parsed_version Version object or `nil` if input is invalid. function M.parse(version, opts) assert(type(version) == 'string', create_err_msg(version)) opts = opts or { strict = false } @@ -447,9 +450,9 @@ end setmetatable(M, { --- Returns the current Nvim version. - ---@return Version + ---@return vim.Version __call = function() - local version = vim.fn.api_info().version ---@type Version + local version = vim.fn.api_info().version ---@type vim.Version -- Workaround: vim.fn.api_info().version reports "prerelease" as a boolean. version.prerelease = version.prerelease and 'dev' or nil return setmetatable(version, Version) -- cgit From 39cc38a87b29d61e7e5342bad2e5156446eb8649 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Sat, 2 Mar 2024 18:51:10 +0900 Subject: fix(lsp): defer writing error msgs (#27688) Context: Nvim catches errors from the user's `on_exit` and rpc handler callbacks and prints the error message. Problem: Printing the error message uses Nvim api functions. But callbacks mentioned above run in `:h lua-loop-callbacks` where most of `vim.api` is not allowed, so Nvim itself raises error. Solution: `vim.schedule()` the error reporting when necessary. --- runtime/lua/vim/lsp/client.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index dfb5137e2a..0f47c57cd5 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -691,8 +691,16 @@ local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'err --- --- @param ... string List to write to the buffer local function err_message(...) - api.nvim_err_writeln(table.concat(vim.tbl_flatten({ ... }))) - api.nvim_command('redraw') + local message = table.concat(vim.tbl_flatten({ ... })) + if vim.in_fast_event() then + vim.schedule(function() + api.nvim_err_writeln(message) + api.nvim_command('redraw') + end) + else + api.nvim_err_writeln(message) + api.nvim_command('redraw') + end end --- @private -- cgit From dc8c086c7e73a9035c34be6416e7c465d61edc0e Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Sat, 2 Mar 2024 23:21:53 +0900 Subject: fix(lsp): directly rename the existing buffers when renaming (#27690) Problem: `vim.lsp.util.rename()` deletes the buffers that are affected by renaming. This has undesireable side effects. For example, when renaming a directory, all buffers under that directory are deleted and windows displaying those buffers are closed. Also, buffer options may change after renaming. Solution: Rename the buffers with :saveas. An alternative approach is to record all the relevant states and restore it after renaming, but that seems to be more complex. In fact, the older version was attempting to restore the states but only partially and incorrectly. --- runtime/lua/vim/lsp/util.lua | 78 ++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 28 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 60d0f0cc83..f8e5b6a90d 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -675,12 +675,23 @@ local function get_bufs_with_prefix(prefix) return buffers end +local function escape_gsub_repl(s) + return (s:gsub('%%', '%%%%')) +end + --- @class vim.lsp.util.rename.Opts --- @inlinedoc --- @field overwrite? boolean --- @field ignoreIfExists? boolean --- Rename old_fname to new_fname +--- +--- Existing buffers are renamed as well, while maintaining their bufnr. +--- +--- It deletes existing buffers that conflict with the renamed file name only when +--- * `opts` requests overwriting; or +--- * the conflicting buffers are not loaded, so that deleting thme does not result in data loss. +--- --- @param old_fname string --- @param new_fname string --- @param opts? vim.lsp.util.rename.Opts Options: @@ -700,24 +711,36 @@ function M.rename(old_fname, new_fname, opts) return end - local oldbufs = {} - local win = nil - - if vim.fn.isdirectory(old_fname_full) == 1 then - oldbufs = get_bufs_with_prefix(old_fname_full) - else - local oldbuf = vim.fn.bufadd(old_fname_full) - table.insert(oldbufs, oldbuf) - win = vim.fn.win_findbuf(oldbuf)[1] - end - - for _, b in ipairs(oldbufs) do - -- There may be pending changes in the buffer - if api.nvim_buf_is_loaded(b) then - api.nvim_buf_call(b, function() - vim.cmd('update!') - end) + local buf_rename = {} ---@type table + local old_fname_pat = '^' .. vim.pesc(old_fname_full) + for b in + vim.iter(get_bufs_with_prefix(old_fname_full)):filter(function(b) + -- No need to care about unloaded or nofile buffers. Also :saveas won't work for them. + return api.nvim_buf_is_loaded(b) + and not vim.list_contains({ 'nofile', 'nowrite' }, vim.bo[b].buftype) + end) + do + -- Renaming a buffer may conflict with another buffer that happens to have the same name. In + -- most cases, this would have been already detected by the file conflict check above, but the + -- conflicting buffer may not be associated with a file. For example, 'buftype' can be "nofile" + -- or "nowrite", or the buffer can be a normal buffer but has not been written to the file yet. + -- Renaming should fail in such cases to avoid losing the contents of the conflicting buffer. + local old_bname = vim.api.nvim_buf_get_name(b) + local new_bname = old_bname:gsub(old_fname_pat, escape_gsub_repl(new_fname)) + if vim.fn.bufexists(new_bname) == 1 then + local existing_buf = vim.fn.bufnr(new_bname) + if api.nvim_buf_is_loaded(existing_buf) and skip then + vim.notify( + new_bname .. ' already exists in the buffer list. Skipping rename.', + vim.log.levels.ERROR + ) + return + end + -- no need to preserve if such a buffer is empty + api.nvim_buf_delete(existing_buf, {}) end + + buf_rename[b] = { from = old_bname, to = new_bname } end local newdir = assert(vim.fs.dirname(new_fname)) @@ -733,17 +756,16 @@ function M.rename(old_fname, new_fname, opts) os.rename(old_undofile, new_undofile) end - if vim.fn.isdirectory(new_fname) == 0 then - local newbuf = vim.fn.bufadd(new_fname) - if win then - vim.fn.bufload(newbuf) - vim.bo[newbuf].buflisted = true - api.nvim_win_set_buf(win, newbuf) - end - end - - for _, b in ipairs(oldbufs) do - api.nvim_buf_delete(b, {}) + for b, rename in pairs(buf_rename) do + -- Rename with :saveas. This does two things: + -- * Unset BF_WRITE_MASK, so that users don't get E13 when they do :write. + -- * Send didClose and didOpen via textDocument/didSave handler. + api.nvim_buf_call(b, function() + vim.cmd('keepalt saveas! ' .. vim.fn.fnameescape(rename.to)) + end) + -- Delete the new buffer with the old name created by :saveas. nvim_buf_delete and + -- :bwipeout are futile because the buffer will be added again somewhere else. + vim.cmd('bdelete! ' .. vim.fn.bufnr(rename.from)) end end -- cgit From 3df1211ebc4c7ec4562d0ad0fa51a24569b81e15 Mon Sep 17 00:00:00 2001 From: Luna Saphie Mittelbach Date: Mon, 4 Mar 2024 00:33:09 +0100 Subject: docs(lua): clarify when `vim.bo`/`vim.wo` acts like `:setlocal` (#27708) --- runtime/lua/vim/_options.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua index bde9421552..b661ddfb22 100644 --- a/runtime/lua/vim/_options.lua +++ b/runtime/lua/vim/_options.lua @@ -271,10 +271,10 @@ vim.go = setmetatable({}, { }) --- Get or set buffer-scoped |options| for the buffer with number {bufnr}. ---- Like `:set` and `:setlocal`. If [{bufnr}] is omitted then the current ---- buffer is used. Invalid {bufnr} or key is an error. +--- If [{bufnr}] is omitted then the current buffer is used. +--- Invalid {bufnr} or key is an error. --- ---- Note: this is equivalent to both `:set` and `:setlocal`. +--- Note: this is equivalent to `:setlocal` for |global-local| options and `:set` otherwise. --- --- Example: --- @@ -287,9 +287,9 @@ vim.go = setmetatable({}, { vim.bo = new_buf_opt_accessor() --- Get or set window-scoped |options| for the window with handle {winid} and ---- buffer with number {bufnr}. Like `:setlocal` if {bufnr} is provided, like ---- `:set` otherwise. If [{winid}] is omitted then the current window is ---- used. Invalid {winid}, {bufnr} or key is an error. +--- buffer with number {bufnr}. Like `:setlocal` if setting a |global-local| option +--- or if {bufnr} is provided, like `:set` otherwise. If [{winid}] is omitted then +--- the current window is used. Invalid {winid}, {bufnr} or key is an error. --- --- Note: only {bufnr} with value `0` (the current buffer in the window) is --- supported. -- cgit From a4290f462ed7dc81e17b09bd27877b106b24b6bd Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 5 Mar 2024 12:06:15 +0000 Subject: docs(lua): improvements for LSP and Diagnostic --- runtime/lua/vim/_inspector.lua | 11 +- runtime/lua/vim/diagnostic.lua | 371 +++++++++++++++++--------------- runtime/lua/vim/lsp.lua | 17 +- runtime/lua/vim/lsp/client.lua | 47 ++-- runtime/lua/vim/lsp/diagnostic.lua | 2 +- runtime/lua/vim/lsp/semantic_tokens.lua | 2 +- runtime/lua/vim/shared.lua | 14 +- 7 files changed, 254 insertions(+), 210 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua index a19d40c50d..2999630fce 100644 --- a/runtime/lua/vim/_inspector.lua +++ b/runtime/lua/vim/_inspector.lua @@ -1,17 +1,20 @@ --- @class vim._inspector.Filter --- @inlinedoc --- ---- Include syntax based highlight groups (defaults to true) +--- Include syntax based highlight groups. +--- (default: `true`) --- @field syntax boolean --- ---- Include treesitter based highlight groups (defaults to true) +--- Include treesitter based highlight groups. +--- (default: `true`) --- @field treesitter boolean --- --- Include extmarks. When `all`, then extmarks without a `hl_group` will also be included. --- (default: true) --- @field extmarks boolean|"all" --- ---- Include semantic token highlights (defaults to true) +--- Include semantic token highlights. +--- (default: true) --- @field semantic_tokens boolean local defaults = { syntax = true, @@ -145,7 +148,7 @@ end ---@param bufnr? integer defaults to the current buffer ---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor ---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor ----@param filter? vim._inspector.Filter (table) see |vim.inspect_pos()| +---@param filter? vim._inspector.Filter function vim.show_pos(bufnr, row, col, filter) local items = vim.inspect_pos(bufnr, row, col, filter) diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 3979e5512c..9483474a40 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -42,15 +42,44 @@ local M = {} --- --- @field namespace? integer +--- Each of the configuration options below accepts one of the following: +--- - `false`: Disable this feature +--- - `true`: Enable this feature, use default settings. +--- - `table`: Enable this feature with overrides. Use an empty table to use default values. +--- - `function`: Function with signature (namespace, bufnr) that returns any of the above. --- @class vim.diagnostic.Opts ---- @field float? boolean|vim.diagnostic.Opts.Float +--- +--- Use underline for diagnostics. +--- (default: `true`) +--- @field underline? boolean|vim.diagnostic.Opts.Underline|fun(namespace: integer, bufnr:integer): vim.diagnostic.Opts.Underline +--- +--- Use virtual text for diagnostics. If multiple diagnostics are set for a +--- namespace, one prefix per diagnostic + the last diagnostic message are +--- shown. +--- (default: `true`) +--- @field virtual_text? boolean|vim.diagnostic.Opts.VirtualText|fun(namespace: integer, bufnr:integer): vim.diagnostic.Opts.VirtualText +--- +--- Use signs for diagnostics |diagnostic-signs|. +--- (default: `true`) +--- @field signs? boolean|vim.diagnostic.Opts.Signs|fun(namespace: integer, bufnr:integer): vim.diagnostic.Opts.Signs +--- +--- Options for floating windows. See |vim.diagnostic.Opts.Float|. +--- @field float? boolean|vim.diagnostic.Opts.Float|fun(namespace: integer, bufnr:integer): vim.diagnostic.Opts.Float +--- +--- Update diagnostics in Insert mode +--- (if `false`, diagnostics are updated on |InsertLeave|) +--- (default: `false) --- @field update_in_insert? boolean ---- @field underline? boolean|vim.diagnostic.Opts.Underline ---- @field virtual_text? boolean|vim.diagnostic.Opts.VirtualText ---- @field signs? boolean|vim.diagnostic.Opts.Signs +--- +--- Sort diagnostics by severity. This affects the order in which signs and +--- virtual text are displayed. When true, higher severities are displayed +--- before lower severities (e.g. ERROR is displayed before WARN). +--- Options: +--- - {reverse}? (boolean) Reverse sort order +--- (default: `false) --- @field severity_sort? boolean|{reverse?:boolean} ---- @class vim.diagnostic.OptsResolved +--- @class (private) vim.diagnostic.OptsResolved --- @field float vim.diagnostic.Opts.Float --- @field update_in_insert boolean --- @field underline vim.diagnostic.Opts.Underline @@ -59,42 +88,156 @@ local M = {} --- @field severity_sort {reverse?:boolean} --- @class vim.diagnostic.Opts.Float +--- +--- Buffer number to show diagnostics from. +--- (default: current buffer) --- @field bufnr? integer +--- +--- Limit diagnostics to the given namespace --- @field namespace? integer +--- +--- Show diagnostics from the whole buffer (`buffer"`, the current cursor line +--- (`line`), or the current cursor position (`cursor`). Shorthand versions +--- are also accepted (`c` for `cursor`, `l` for `line`, `b` for `buffer`). +--- (default: `line`) --- @field scope? 'line'|'buffer'|'cursor'|'c'|'l'|'b' +--- +--- If {scope} is "line" or "cursor", use this position rather than the cursor +--- position. If a number, interpreted as a line number; otherwise, a +--- (row, col) tuple. --- @field pos? integer|{[1]:integer,[2]:integer} +--- +--- Sort diagnostics by severity. +--- Overrides the setting from |vim.diagnostic.config()|. +--- (default: `false`) --- @field severity_sort? boolean|{reverse?:boolean} +--- +--- See |diagnostic-severity|. +--- Overrides the setting from |vim.diagnostic.config()|. --- @field severity? vim.diagnostic.SeverityFilter +--- +--- String to use as the header for the floating window. If a table, it is +--- interpreted as a `[text, hl_group]` tuple. +--- Overrides the setting from |vim.diagnostic.config()|. --- @field header? string|{[1]:string,[2]:any} ---- @field source? boolean|string +--- +--- Include the diagnostic source in the message. +--- Use "if_many" to only show sources if there is more than one source of +--- diagnostics in the buffer. Otherwise, any truthy value means to always show +--- the diagnostic source. +--- Overrides the setting from |vim.diagnostic.config()|. +--- @field source? boolean|'if_many' +--- +--- A function that takes a diagnostic as input and returns a string. +--- The return value is the text used to display the diagnostic. +--- Overrides the setting from |vim.diagnostic.config()|. --- @field format? fun(diagnostic:vim.Diagnostic): string +--- +--- Prefix each diagnostic in the floating window: +--- - If a `function`, {i} is the index of the diagnostic being evaluated and +--- {total} is the total number of diagnostics displayed in the window. The +--- function should return a `string` which is prepended to each diagnostic +--- in the window as well as an (optional) highlight group which will be +--- used to highlight the prefix. +--- - If a `table`, it is interpreted as a `[text, hl_group]` tuple as +--- in |nvim_echo()| +--- - If a `string`, it is prepended to each diagnostic in the window with no +--- highlight. +--- Overrides the setting from |vim.diagnostic.config()|. --- @field prefix? string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string) +--- +--- Same as {prefix}, but appends the text to the diagnostic instead of +--- prepending it. +--- Overrides the setting from |vim.diagnostic.config()|. --- @field suffix? string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string) +--- --- @field focus_id? string --- @class vim.diagnostic.Opts.Underline +--- +--- Only underline diagnostics matching the given +--- severity |diagnostic-severity|. --- @field severity? vim.diagnostic.SeverityFilter --- @class vim.diagnostic.Opts.VirtualText +--- +--- Only show virtual text for diagnostics matching the given +--- severity |diagnostic-severity| --- @field severity? vim.diagnostic.SeverityFilter ---- @field source? boolean|string ---- @field prefix? string|function ---- @field suffix? string|function +--- +--- Include the diagnostic source in virtual text. Use `'if_many'` to only +--- show sources if there is more than one diagnostic source in the buffer. +--- Otherwise, any truthy value means to always show the diagnostic source. +--- @field source? boolean|"if_many" +--- +--- Amount of empty spaces inserted at the beginning of the virtual text. --- @field spacing? integer ---- @field format? function +--- +--- Prepend diagnostic message with prefix. If a `function`, {i} is the index +--- of the diagnostic being evaluated, and {total} is the total number of +--- diagnostics for the line. This can be used to render diagnostic symbols +--- or error codes. +--- @field prefix? string|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string) +--- +--- Append diagnostic message with suffix. +--- This can be used to render an LSP diagnostic error code. +--- @field suffix? string|(fun(diagnostic:vim.Diagnostic): string) +--- +--- The return value is the text used to display the diagnostic. Example: +--- ```lua +--- function(diagnostic) +--- if diagnostic.severity == vim.diagnostic.severity.ERROR then +--- return string.format("E: %s", diagnostic.message) +--- end +--- return diagnostic.message +--- end +--- ``` +--- @field format? fun(diagnostic:vim.Diagnostic): string +--- +--- See |nvim_buf_set_extmark()|. --- @field hl_mode? 'replace'|'combine'|'blend' +--- +--- See |nvim_buf_set_extmark()|. --- @field virt_text? {[1]:string,[2]:any}[] +--- +--- See |nvim_buf_set_extmark()|. --- @field virt_text_pos? 'eol'|'overlay'|'right_align'|'inline' +--- +--- See |nvim_buf_set_extmark()|. --- @field virt_text_win_col? integer +--- +--- See |nvim_buf_set_extmark()|. --- @field virt_text_hide? boolean --- @class vim.diagnostic.Opts.Signs +--- +--- Only show virtual text for diagnostics matching the given +--- severity |diagnostic-severity| --- @field severity? vim.diagnostic.SeverityFilter +--- +--- Base priority to use for signs. When {severity_sort} is used, the priority +--- of a sign is adjusted based on its severity. +--- Otherwise, all signs use the same priority. +--- (default: `10`) --- @field priority? integer +--- +--- A table mapping |diagnostic-severity| to the sign text to display in the +--- sign column. The default is to use `"E"`, `"W"`, `"I"`, and `"H"` for errors, +--- warnings, information, and hints, respectively. Example: +--- ```lua +--- vim.diagnostic.config({ +--- signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } } +--- }) +--- ``` --- @field text? table +--- +--- A table mapping |diagnostic-severity| to the highlight group used for the +--- line number where the sign is placed. --- @field numhl? table +--- +--- A table mapping |diagnostic-severity| to the highlight group used for the +--- whole line the sign is placed in. --- @field linehl? table ---- @field texthl? table --- @nodoc --- @enum vim.diagnostic.Severity @@ -752,83 +895,11 @@ end --- --- then virtual text will not be enabled for those diagnostics. --- ----@note Each of the configuration options below accepts one of the following: ---- - `false`: Disable this feature ---- - `true`: Enable this feature, use default settings. ---- - `table`: Enable this feature with overrides. Use an empty table to use default values. ---- - `function`: Function with signature (namespace, bufnr) that returns any of the above. ---- ----@param opts vim.diagnostic.Opts? (table?) When omitted or "nil", retrieve the current ---- configuration. Otherwise, a configuration table with the following keys: ---- - underline: (default true) Use underline for diagnostics. Options: ---- * severity: Only underline diagnostics matching the given ---- severity |diagnostic-severity| ---- - virtual_text: (default true) Use virtual text for diagnostics. If multiple diagnostics ---- are set for a namespace, one prefix per diagnostic + the last diagnostic ---- message are shown. In addition to the options listed below, the ---- "virt_text" options of |nvim_buf_set_extmark()| may also be used here ---- (e.g. "virt_text_pos" and "hl_mode"). ---- Options: ---- * severity: Only show virtual text for diagnostics matching the given ---- severity |diagnostic-severity| ---- * source: (boolean or string) Include the diagnostic source in virtual ---- text. Use "if_many" to only show sources if there is more than ---- one diagnostic source in the buffer. Otherwise, any truthy value ---- means to always show the diagnostic source. ---- * spacing: (number) Amount of empty spaces inserted at the beginning ---- of the virtual text. ---- * prefix: (string or function) prepend diagnostic message with prefix. ---- If a function, it must have the signature (diagnostic, i, total) ---- -> string, where {diagnostic} is of type |diagnostic-structure|, ---- {i} is the index of the diagnostic being evaluated, and {total} ---- is the total number of diagnostics for the line. This can be ---- used to render diagnostic symbols or error codes. ---- * suffix: (string or function) Append diagnostic message with suffix. ---- If a function, it must have the signature (diagnostic) -> ---- string, where {diagnostic} is of type |diagnostic-structure|. ---- This can be used to render an LSP diagnostic error code. ---- * format: (function) A function that takes a diagnostic as input and ---- returns a string. The return value is the text used to display ---- the diagnostic. Example: ---- ```lua ---- function(diagnostic) ---- if diagnostic.severity == vim.diagnostic.severity.ERROR then ---- return string.format("E: %s", diagnostic.message) ---- end ---- return diagnostic.message ---- end ---- ``` ---- - signs: (default true) Use signs for diagnostics |diagnostic-signs|. Options: ---- * severity: Only show signs for diagnostics matching the given ---- severity |diagnostic-severity| ---- * priority: (number, default 10) Base priority to use for signs. When ---- {severity_sort} is used, the priority of a sign is adjusted based on ---- its severity. Otherwise, all signs use the same priority. ---- * text: (table) A table mapping |diagnostic-severity| to the sign text ---- to display in the sign column. The default is to use "E", "W", "I", and "H" ---- for errors, warnings, information, and hints, respectively. Example: ---- ```lua ---- vim.diagnostic.config({ ---- signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } } ---- }) ---- ``` ---- * numhl: (table) A table mapping |diagnostic-severity| to the highlight ---- group used for the line number where the sign is placed. ---- * linehl: (table) A table mapping |diagnostic-severity| to the highlight group ---- used for the whole line the sign is placed in. ---- - float: Options for floating windows. See |vim.diagnostic.open_float()|. ---- - update_in_insert: (default false) Update diagnostics in Insert mode (if false, ---- diagnostics are updated on InsertLeave) ---- - severity_sort: (default false) Sort diagnostics by severity. This affects the order in ---- which signs and virtual text are displayed. When true, higher severities ---- are displayed before lower severities (e.g. ERROR is displayed before WARN). ---- Options: ---- * reverse: (boolean) Reverse sort order ---- ----@param namespace integer? Update the options for the given namespace. When omitted, update the ---- global diagnostic options. ---- ----@return vim.diagnostic.Opts? (table?) table of current diagnostic config if `opts` is omitted. +---@param opts vim.diagnostic.Opts? When omitted or `nil`, retrieve the current +--- configuration. Otherwise, a configuration table (see |vim.diagnostic.Opts|). +---@param namespace integer? Update the options for the given namespace. +--- When omitted, update the global diagnostic options. +---@return vim.diagnostic.Opts? : Current diagnostic config if {opts} is omitted. function M.config(opts, namespace) vim.validate({ opts = { opts, 't', true }, @@ -873,8 +944,8 @@ end --- ---@param namespace integer The diagnostic namespace ---@param bufnr integer Buffer number ----@param diagnostics vim.Diagnostic[] A list of diagnostic items |diagnostic-structure| ----@param opts? vim.diagnostic.Opts (table) Display options to pass to |vim.diagnostic.show()| +---@param diagnostics vim.Diagnostic[] +---@param opts? vim.diagnostic.Opts Display options to pass to |vim.diagnostic.show()| function M.set(namespace, bufnr, diagnostics, opts) vim.validate({ namespace = { namespace, 'n' }, @@ -908,7 +979,7 @@ end --- Get namespace metadata. --- ---@param namespace integer Diagnostic namespace ----@return vim.diagnostic.NS (table) Namespace metadata +---@return vim.diagnostic.NS : Namespace metadata function M.get_namespace(namespace) vim.validate({ namespace = { namespace, 'n' } }) if not all_namespaces[namespace] then @@ -933,22 +1004,21 @@ end --- Get current diagnostic namespaces. --- ----@return table A list of active diagnostic namespaces |vim.diagnostic|. +---@return table : List of active diagnostic namespaces |vim.diagnostic|. function M.get_namespaces() return vim.deepcopy(all_namespaces, true) end --- Get current diagnostics. --- ---- Modifying diagnostics in the returned table has no effect. To set diagnostics in a buffer, use |vim.diagnostic.set()|. +--- Modifying diagnostics in the returned table has no effect. +--- To set diagnostics in a buffer, use |vim.diagnostic.set()|. --- ---@param bufnr integer? Buffer number to get diagnostics from. Use 0 for ---- current buffer or nil for all buffers. ----@param opts? vim.diagnostic.GetOpts (table) A table with the following keys: ---- - namespace: (number) Limit diagnostics to the given namespace. ---- - lnum: (number) Limit diagnostics to the given line number. ---- - severity: See |diagnostic-severity|. ----@return vim.Diagnostic[] table A list of diagnostic items |diagnostic-structure|. Keys `bufnr`, `end_lnum`, `end_col`, and `severity` are guaranteed to be present. +--- current buffer or nil for all buffers. +---@param opts? vim.diagnostic.GetOpts +---@return vim.Diagnostic[] : Fields `bufnr`, `end_lnum`, `end_col`, and `severity` +--- are guaranteed to be present. function M.get(bufnr, opts) vim.validate({ bufnr = { bufnr, 'n', true }, @@ -962,11 +1032,9 @@ end --- ---@param bufnr? integer Buffer number to get diagnostics from. Use 0 for --- current buffer or nil for all buffers. ----@param opts? table A table with the following keys: ---- - namespace: (number) Limit diagnostics to the given namespace. ---- - lnum: (number) Limit diagnostics to the given line number. ---- - severity: See |diagnostic-severity|. ----@return table A table with actually present severity values as keys (see |diagnostic-severity|) and integer counts as values. +---@param opts? vim.diagnostic.GetOpts +---@return table : Table with actually present severity values as keys +--- (see |diagnostic-severity|) and integer counts as values. function M.count(bufnr, opts) vim.validate({ bufnr = { bufnr, 'n', true }, @@ -984,8 +1052,8 @@ end --- Get the previous diagnostic closest to the cursor position. --- ----@param opts? vim.diagnostic.GotoOpts (table) See |vim.diagnostic.goto_next()| ----@return vim.Diagnostic? Previous diagnostic +---@param opts? vim.diagnostic.GotoOpts +---@return vim.Diagnostic? : Previous diagnostic function M.get_prev(opts) opts = opts or {} @@ -998,9 +1066,9 @@ end --- Return the position of the previous diagnostic in the current buffer. --- ----@param opts? vim.diagnostic.GotoOpts (table) See |vim.diagnostic.goto_next()| ----@return table|false: Previous diagnostic position as a (row, col) tuple or false if there is no ---- prior diagnostic +---@param opts? vim.diagnostic.GotoOpts +---@return table|false: Previous diagnostic position as a `(row, col)` tuple +--- or `false` if there is no prior diagnostic. function M.get_prev_pos(opts) local prev = M.get_prev(opts) if not prev then @@ -1011,14 +1079,14 @@ function M.get_prev_pos(opts) end --- Move to the previous diagnostic in the current buffer. ----@param opts? vim.diagnostic.GotoOpts (table) See |vim.diagnostic.goto_next()| +---@param opts? vim.diagnostic.GotoOpts function M.goto_prev(opts) return diagnostic_move_pos(opts, M.get_prev_pos(opts)) end --- Get the next diagnostic closest to the cursor position. --- ----@param opts? vim.diagnostic.GotoOpts (table) See |vim.diagnostic.goto_next()| +---@param opts? vim.diagnostic.GotoOpts ---@return vim.Diagnostic? : Next diagnostic function M.get_next(opts) opts = opts or {} @@ -1032,8 +1100,8 @@ end --- Return the position of the next diagnostic in the current buffer. --- ----@param opts? vim.diagnostic.GotoOpts (table) See |vim.diagnostic.goto_next()| ----@return table|false : Next diagnostic position as a (row, col) tuple or false if no next +---@param opts? vim.diagnostic.GotoOpts +---@return table|false : Next diagnostic position as a `(row, col)` tuple or false if no next --- diagnostic. function M.get_next_pos(opts) local next = M.get_next(opts) @@ -1046,7 +1114,6 @@ end --- A table with the following keys: --- @class vim.diagnostic.GetOpts ---- @inlinedoc --- --- Limit diagnostics to the given namespace. --- @field namespace? integer @@ -1059,13 +1126,10 @@ end --- Configuration table with the following keys: --- @class vim.diagnostic.GotoOpts : vim.diagnostic.GetOpts ---- @inlinedoc ---- ---- Only consider diagnostics from the given namespace. ---- @field namespace integer --- ---- Cursor position as a (row, col) tuple. ---- See |nvim_win_get_cursor()|. Defaults to the current cursor position. +--- Cursor position as a `(row, col)` tuple. +--- See |nvim_win_get_cursor()|. +--- (default: current cursor position) --- @field cursor_position? {[1]:integer,[2]:integer} --- --- Whether to loop around file or not. Similar to 'wrapscan'. @@ -1075,11 +1139,10 @@ end --- See |diagnostic-severity|. --- @field severity vim.diagnostic.Severity --- ---- If "true", call |vim.diagnostic.open_float()| ---- after moving. If a table, pass the table as the {opts} parameter ---- to |vim.diagnostic.open_float()|. Unless overridden, the float will show ---- diagnostics at the new cursor position (as if "cursor" were passed to ---- the "scope" option). +--- If `true`, call |vim.diagnostic.open_float()| after moving. +--- If a table, pass the table as the {opts} parameter to |vim.diagnostic.open_float()|. +--- Unless overridden, the float will show diagnostics at the new cursor +--- position (as if "cursor" were passed to the "scope" option). --- (default: `true`) --- @field float? boolean|vim.diagnostic.Opts.Float --- @@ -1141,7 +1204,7 @@ M.handlers.signs = { -- Handle legacy diagnostic sign definitions -- These were deprecated in 0.10 and will be removed in 0.12 - if opts.signs and not opts.signs.text and not opts.signs.numhl and not opts.signs.texthl then + if opts.signs and not opts.signs.text and not opts.signs.numhl then for _, v in ipairs({ 'Error', 'Warn', 'Info', 'Hint' }) do local name = string.format('DiagnosticSign%s', v) local sign = vim.fn.sign_getdefined(name)[1] @@ -1476,7 +1539,7 @@ end --- without saving them or to display only a subset of --- diagnostics. May not be used when {namespace} --- or {bufnr} is nil. ----@param opts? vim.diagnostic.Opts (table) Display options. See |vim.diagnostic.config()|. +---@param opts? vim.diagnostic.Opts Display options. function M.show(namespace, bufnr, diagnostics, opts) vim.validate({ namespace = { namespace, 'n', true }, @@ -1552,46 +1615,7 @@ end --- Show diagnostics in a floating window. --- ----@param opts vim.diagnostic.Opts.Float? (table?) Configuration table with the same keys ---- as |vim.lsp.util.open_floating_preview()| in addition to the following: ---- - bufnr: (number) Buffer number to show diagnostics from. ---- Defaults to the current buffer. ---- - namespace: (number) Limit diagnostics to the given namespace ---- - scope: (string, default "line") Show diagnostics from the whole buffer ("buffer"), ---- the current cursor line ("line"), or the current cursor position ("cursor"). ---- Shorthand versions are also accepted ("c" for "cursor", "l" for "line", "b" ---- for "buffer"). ---- - pos: (number or table) If {scope} is "line" or "cursor", use this position rather ---- than the cursor position. If a number, interpreted as a line number; ---- otherwise, a (row, col) tuple. ---- - severity_sort: (default false) Sort diagnostics by severity. Overrides the setting ---- from |vim.diagnostic.config()|. ---- - severity: See |diagnostic-severity|. Overrides the setting ---- from |vim.diagnostic.config()|. ---- - header: (string or table) String to use as the header for the floating window. If a ---- table, it is interpreted as a [text, hl_group] tuple. Overrides the setting ---- from |vim.diagnostic.config()|. ---- - source: (boolean or string) Include the diagnostic source in the message. ---- Use "if_many" to only show sources if there is more than one source of ---- diagnostics in the buffer. Otherwise, any truthy value means to always show ---- the diagnostic source. Overrides the setting from |vim.diagnostic.config()|. ---- - format: (function) A function that takes a diagnostic as input and returns a ---- string. The return value is the text used to display the diagnostic. ---- Overrides the setting from |vim.diagnostic.config()|. ---- - prefix: (function, string, or table) Prefix each diagnostic in the floating ---- window. If a function, it must have the signature (diagnostic, i, ---- total) -> (string, string), where {i} is the index of the diagnostic ---- being evaluated and {total} is the total number of diagnostics ---- displayed in the window. The function should return a string which ---- is prepended to each diagnostic in the window as well as an ---- (optional) highlight group which will be used to highlight the ---- prefix. If {prefix} is a table, it is interpreted as a [text, ---- hl_group] tuple as in |nvim_echo()|; otherwise, if {prefix} is a ---- string, it is prepended to each diagnostic in the window with no ---- highlight. ---- Overrides the setting from |vim.diagnostic.config()|. ---- - suffix: Same as {prefix}, but appends the text to the diagnostic instead of ---- prepending it. Overrides the setting from |vim.diagnostic.config()|. +---@param opts vim.diagnostic.Opts.Float? ---@return integer? float_bufnr ---@return integer? win_id function M.open_float(opts, ...) @@ -1963,8 +1987,7 @@ end --- WARNING filename:27:3: Variable 'foo' does not exist --- ``` --- ---- This can be parsed into a diagnostic |diagnostic-structure| ---- with: +--- This can be parsed into |vim.Diagnostic| structure with: --- --- ```lua --- local s = "WARNING filename:27:3: Variable 'foo' does not exist" @@ -1975,14 +1998,14 @@ end --- ---@param str string String to parse diagnostics from. ---@param pat string Lua pattern with capture groups. ----@param groups string[] List of fields in a |diagnostic-structure| to +---@param groups string[] List of fields in a |vim.Diagnostic| structure to --- associate with captures from {pat}. ---@param severity_map table A table mapping the severity field from {groups} --- with an item from |vim.diagnostic.severity|. ---@param defaults table? Table of default values for any fields not listed in {groups}. --- When omitted, numeric values default to 0 and "severity" defaults to --- ERROR. ----@return vim.Diagnostic?: |diagnostic-structure| or `nil` if {pat} fails to match {str}. +---@return vim.Diagnostic?: |vim.Diagnostic| structure or `nil` if {pat} fails to match {str}. function M.match(str, pat, groups, severity_map, defaults) vim.validate({ str = { str, 's' }, @@ -2030,8 +2053,8 @@ local errlist_type_map = { --- Convert a list of diagnostics to a list of quickfix items that can be --- passed to |setqflist()| or |setloclist()|. --- ----@param diagnostics vim.Diagnostic[] List of diagnostics |diagnostic-structure|. ----@return table[] of quickfix list items |setqflist-what| +---@param diagnostics vim.Diagnostic[] +---@return table[] : Quickfix list items |setqflist-what| function M.toqflist(diagnostics) vim.validate({ diagnostics = { @@ -2071,7 +2094,7 @@ end --- Convert a list of quickfix items to a list of diagnostics. --- ---@param list table[] List of quickfix items from |getqflist()| or |getloclist()|. ----@return vim.Diagnostic[] array of |diagnostic-structure| +---@return vim.Diagnostic[] function M.fromqflist(list) vim.validate({ list = { diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 8ebf4de3cb..ef5d9d7cff 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -961,16 +961,15 @@ end --- --- Calls |vim.lsp.buf_request_all()| but blocks Nvim while awaiting the result. --- Parameters are the same as |vim.lsp.buf_request_all()| but the result is ---- different. Waits a maximum of {timeout_ms} (default 1000) ms. +--- different. Waits a maximum of {timeout_ms}. --- ----@param bufnr (integer) Buffer handle, or 0 for current. ----@param method (string) LSP method name ----@param params (table|nil) Parameters to send to the server ----@param timeout_ms (integer|nil) Maximum time in milliseconds to wait for a ---- result. Defaults to 1000 ---- ----@return table|nil (table) result Map of client_id:request_result. ----@return string|nil err On timeout, cancel, or error, `err` is a string describing the failure reason, and `result` is nil. +---@param bufnr integer Buffer handle, or 0 for current. +---@param method string LSP method name +---@param params table? Parameters to send to the server +---@param timeout_ms integer? Maximum time in milliseconds to wait for a result. +--- (default: `1000`) +---@return table? result Map of client_id:request_result. +---@return string? err On timeout, cancel, or error, `err` is a string describing the failure reason, and `result` is nil. function lsp.buf_request_sync(bufnr, method, params, timeout_ms) local request_results diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index 0f47c57cd5..6dd898bea7 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -11,6 +11,24 @@ local validate = vim.validate --- @alias vim.lsp.client.on_exit_cb fun(code: integer, signal: integer, client_id: integer) --- @alias vim.lsp.client.before_init_cb fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig) +--- @class vim.lsp.Client.Flags +--- @inlinedoc +--- +--- Allow using incremental sync for buffer edits +--- (defailt: `true`) +--- @field allow_incremental_sync? boolean +--- +--- Debounce `didChange` notifications to the server by the given number in milliseconds. +--- No debounce occurs if `nil`. +--- (default: `150`) +--- @field debounce_text_changes integer +--- +--- Milliseconds to wait for server to exit cleanly after sending the +--- "shutdown" request before sending kill -15. If set to false, nvim exits +--- immediately after sending the "shutdown" request to the server. +--- (default: `false`) +--- @field exit_timeout integer|false + --- @class vim.lsp.ClientConfig --- command string[] that launches the language --- server (treated as in |jobstart()|, must be absolute or on `$PATH`, shell constructs like @@ -55,8 +73,8 @@ local validate = vim.validate --- Map of language server method names to |lsp-handler| --- @field handlers? table --- ---- Map with language server specific settings. These are returned to the language server if ---- requested via `workspace/configuration`. Keys are case-sensitive. +--- Map with language server specific settings. +--- See the {settings} in |vim.lsp.Client|. --- @field settings? table --- --- Table that maps string of clientside commands to user-defined functions. @@ -87,36 +105,29 @@ local validate = vim.validate --- Callback 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 |vim.lsp.start_client()|. --- You can use this to modify parameters before they are sent. ---- @field before_init? vim.lsp.client.before_init_cb +--- @field before_init? fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig) --- --- Callback 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. ---- @field on_init? elem_or_list +--- @field on_init? elem_or_list --- --- Callback invoked on client exit. --- - code: exit code of the process --- - signal: number describing the signal used to terminate (if any) --- - client_id: client handle ---- @field on_exit? elem_or_list +--- @field on_exit? elem_or_list --- --- Callback invoked when client attaches to a buffer. ---- @field on_attach? elem_or_list +--- @field on_attach? elem_or_list --- --- Passed directly to the language server in the initialize request. Invalid/empty values will --- (default: "off") --- @field trace? 'off'|'messages'|'verbose' --- --- A table with flags for the client. The current (experimental) flags are: ---- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits ---- - debounce_text_changes (number, default 150): Debounce didChange ---- notifications to the server by the given number in milliseconds. No debounce ---- occurs if nil ---- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to ---- exit cleanly after sending the "shutdown" request before sending kill -15. ---- If set to false, nvim exits immediately after sending the "shutdown" request to the server. ---- @field flags? table +--- @field flags? vim.lsp.Client.Flags --- --- Directory where the LSP server will base its workspaceFolders, rootUri, and rootPath on initialization. --- @field root_dir? string @@ -189,8 +200,14 @@ local validate = vim.validate --- Client commands take precedence over the global command registry. --- @field commands table --- +--- Map with language server specific settings. These are returned to the +--- language server if requested via `workspace/configuration`. Keys are +--- case-sensitive. --- @field settings table ---- @field flags table +--- +--- A table with flags for the client. The current (experimental) flags are: +--- @field flags vim.lsp.Client.Flags +--- --- @field get_language_id fun(bufnr: integer, filetype: string): string --- --- The capabilities provided by the client (editor or tool) diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 6156821093..e4620897ac 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -321,7 +321,7 @@ end ---@param _ lsp.ResponseError? ---@param result lsp.DocumentDiagnosticReport ---@param ctx lsp.HandlerContext ----@param config table Configuration table (see |vim.diagnostic.config()|). +---@param config vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|). function M.on_diagnostic(_, result, ctx, config) if result == nil or result.kind == 'unchanged' then return diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index 92546e8520..20ac0a125f 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -572,7 +572,7 @@ local M = {} --- ---@param bufnr integer ---@param client_id integer ----@param opts (nil|table) Optional keyword arguments +---@param opts? table Optional keyword arguments --- - debounce (integer, default: 200): Debounce token requests --- to the server by the given number in milliseconds function M.start(bufnr, client_id, opts) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index ec70630df3..18d7c8b13e 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -102,7 +102,7 @@ end --- @param s string String to split --- @param sep string Separator or pattern --- @param opts? vim.gsplit.Opts Keyword arguments |kwargs|: ---- @return fun():string|nil (function) Iterator over the split components +--- @return fun():string? : Iterator over the split components function vim.gsplit(s, sep, opts) local plain --- @type boolean? local trimempty = false @@ -245,8 +245,8 @@ end --- Apply a function to all values of a table. --- ---@generic T ----@param func fun(value: T): any (function) Function ----@param t table (table) Table +---@param func fun(value: T): any Function +---@param t table Table ---@return table : Table of transformed values function vim.tbl_map(func, t) vim.validate({ func = { func, 'c' }, t = { t, 't' } }) @@ -570,8 +570,10 @@ end --- ---@see Based on https://github.com/premake/premake-core/blob/master/src/base/table.lua --- ----@param t table Dict-like table ----@return function # |for-in| iterator over sorted keys and their values +---@generic T: table, K, V +---@param t T Dict-like table +---@return fun(table: table, index?: K):K, V # |for-in| iterator over sorted keys and their values +---@return T function vim.spairs(t) vim.validate({ t = { t, 't' } }) --- @cast t table @@ -1018,7 +1020,7 @@ do --- - |Ringbuf:clear()| --- ---@param size integer - ---@return vim.Ringbuf ringbuf (table) + ---@return vim.Ringbuf ringbuf function vim.ringbuf(size) local ringbuf = { _items = {}, -- cgit From ea44f74d84f87ce5aff2ef7797be986900bd74a6 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 6 Mar 2024 10:03:55 +0000 Subject: refactor(types): more fixes --- runtime/lua/vim/_editor.lua | 20 ++++++--- runtime/lua/vim/_init_packages.lua | 6 ++- runtime/lua/vim/_meta/api_keysets_extra.lua | 2 +- runtime/lua/vim/_options.lua | 64 ++++++++++++++++++++++------- runtime/lua/vim/fs.lua | 12 +++--- runtime/lua/vim/loader.lua | 2 +- runtime/lua/vim/shared.lua | 3 +- 7 files changed, 78 insertions(+), 31 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index d14007312e..c588802193 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -275,6 +275,7 @@ do for _, line in ipairs(lines) do nchars = nchars + line:len() end + --- @type integer, integer local row, col = unpack(vim.api.nvim_win_get_cursor(0)) local bufline = vim.api.nvim_buf_get_lines(0, row - 1, row, true)[1] local firstline = lines[1] @@ -355,8 +356,11 @@ end -- vim.fn.{func}(...) ---@nodoc vim.fn = setmetatable({}, { + --- @param t table + --- @param key string + --- @return function __index = function(t, key) - local _fn + local _fn --- @type function if vim.api[key] ~= nil then _fn = function() error(string.format('Tried to call API function with vim.fn: use vim.api.%s instead', key)) @@ -620,7 +624,7 @@ function vim.notify(msg, level, opts) -- luacheck: no unused args end do - local notified = {} + local notified = {} --- @type table --- Displays a notification only one time. --- @@ -641,7 +645,7 @@ do end end -local on_key_cbs = {} +local on_key_cbs = {} --- @type table --- Adds Lua function {fn} with namespace id {ns_id} as a listener to every, --- yes every, input key. @@ -711,6 +715,7 @@ end --- 2. Can we get it to return things from global namespace even with `print(` in front. --- --- @param pat string +--- @return any[], integer function vim._expand_pat(pat, env) env = env or _G @@ -743,7 +748,7 @@ function vim._expand_pat(pat, env) if type(final_env) ~= 'table' then return {}, 0 end - local key + local key --- @type any -- Normally, we just have a string -- Just attempt to get the string directly from the environment @@ -785,7 +790,8 @@ function vim._expand_pat(pat, env) end end - local keys = {} + local keys = {} --- @type table + --- @param obj table local function insert_keys(obj) for k, _ in pairs(obj) do if type(k) == 'string' and string.sub(k, 1, string.len(match_part)) == match_part then @@ -813,6 +819,7 @@ function vim._expand_pat(pat, env) end --- @param lua_string string +--- @return (string|string[])[], integer vim._expand_pat_get_parts = function(lua_string) local parts = {} @@ -870,6 +877,7 @@ vim._expand_pat_get_parts = function(lua_string) end end + --- @param val any[] parts = vim.tbl_filter(function(val) return #val > 0 end, parts) @@ -880,7 +888,7 @@ end do -- Ideally we should just call complete() inside omnifunc, though there are -- some bugs, so fake the two-step dance for now. - local matches + local matches --- @type any[] --- Omnifunc for completing Lua values from the runtime Lua interpreter, --- similar to the builtin completion for the `:lua` command. diff --git a/runtime/lua/vim/_init_packages.lua b/runtime/lua/vim/_init_packages.lua index 71ac3bcfcd..d0bb91114e 100644 --- a/runtime/lua/vim/_init_packages.lua +++ b/runtime/lua/vim/_init_packages.lua @@ -1,5 +1,5 @@ -local pathtrails = {} -vim._so_trails = {} +local pathtrails = {} --- @type table ta +vim._so_trails = {} --- @type string[] for s in (package.cpath .. ';'):gmatch('[^;]*;') do s = s:sub(1, -2) -- Strip trailing semicolon -- Find out path patterns. pathtrail should contain something like @@ -65,6 +65,7 @@ vim._submodules = { -- These are for loading runtime modules in the vim namespace lazily. setmetatable(vim, { + --- @param t table __index = function(t, key) if vim._submodules[key] then t[key] = require('vim.' .. key) @@ -73,6 +74,7 @@ setmetatable(vim, { require('vim._inspector') return t[key] elseif vim.startswith(key, 'uri_') then + --- @type any? local val = require('vim.uri')[key] if val ~= nil then -- Expose all `vim.uri` functions on the `vim` module. diff --git a/runtime/lua/vim/_meta/api_keysets_extra.lua b/runtime/lua/vim/_meta/api_keysets_extra.lua index 8e34ee534c..d61dd2c02f 100644 --- a/runtime/lua/vim/_meta/api_keysets_extra.lua +++ b/runtime/lua/vim/_meta/api_keysets_extra.lua @@ -129,7 +129,7 @@ error('Cannot require a meta file') --- @field last_set_chan integer --- @field type 'string'|'boolean'|'number' --- @field default string|boolean|integer ---- @field allow_duplicates boolean +--- @field allows_duplicates boolean --- @class vim.api.keyset.parse_cmd.mods --- @field filter { force: boolean, pattern: string } diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua index b661ddfb22..60dcf8c64a 100644 --- a/runtime/lua/vim/_options.lua +++ b/runtime/lua/vim/_options.lua @@ -105,6 +105,10 @@ local key_value_options = { winhl = true, } +--- @nodoc +--- @class vim._option.Info : vim.api.keyset.get_option_info +--- @field metatype 'boolean'|'string'|'number'|'map'|'array'|'set' + --- Convert a vimoption_T style dictionary to the correct OptionType associated with it. ---@return string local function get_option_metatype(name, info) @@ -123,8 +127,10 @@ local function get_option_metatype(name, info) end --- @param name string +--- @return vim._option.Info local function get_options_info(name) local info = api.nvim_get_option_info2(name, {}) + --- @cast info vim._option.Info info.metatype = get_option_metatype(name, info) return info end @@ -139,7 +145,6 @@ end --- vim.env.FOO = 'bar' --- print(vim.env.TERM) --- ``` ----@param var string vim.env = setmetatable({}, { __index = function(_, k) local v = vim.fn.getenv(k) @@ -311,9 +316,15 @@ vim.wo = new_win_opt_accessor() --- For information on how to use, see :help vim.opt --- Preserves the order and does not mutate the original list +--- @generic T +--- @param t T[] +--- @return T[] local function remove_duplicate_values(t) + --- @type table, table local result, seen = {}, {} - for _, v in ipairs(t) do + for _, v in + ipairs(t --[[@as any[] ]]) + do if not seen[v] then table.insert(result, v) end @@ -324,8 +335,11 @@ local function remove_duplicate_values(t) return result end --- Check whether the OptionTypes is allowed for vim.opt --- If it does not match, throw an error which indicates which option causes the error. +--- Check whether the OptionTypes is allowed for vim.opt +--- If it does not match, throw an error which indicates which option causes the error. +--- @param name any +--- @param value any +--- @param types string[] local function assert_valid_value(name, value, types) local type_of_value = type(value) for _, valid_type in ipairs(types) do @@ -352,6 +366,8 @@ local function tbl_merge(left, right) return vim.tbl_extend('force', left, right) end +--- @param t table +--- @param value any|any[] local function tbl_remove(t, value) if type(value) == 'string' then t[value] = nil @@ -380,6 +396,8 @@ local to_vim_value = { number = passthrough, string = passthrough, + --- @param info vim._option.Info + --- @param value string|table set = function(info, value) if type(value) == 'string' then return value @@ -407,6 +425,8 @@ local to_vim_value = { end end, + --- @param info vim._option.Info + --- @param value string|string[] array = function(info, value) if type(value) == 'string' then return value @@ -417,6 +437,7 @@ local to_vim_value = { return table.concat(value, ',') end, + --- @param value string|table map = function(_, value) if type(value) == 'string' then return value @@ -466,7 +487,8 @@ local to_lua_value = { end -- Handles unescaped commas in a list. - if string.find(value, ',,,') then + if value:find(',,,') then + --- @type string, string local left, right = unpack(vim.split(value, ',,,')) local result = {} @@ -479,8 +501,9 @@ local to_lua_value = { return result end - if string.find(value, ',^,,', 1, true) then - local left, right = unpack(vim.split(value, ',^,,', true)) + if value:find(',^,,', 1, true) then + --- @type string, string + local left, right = unpack(vim.split(value, ',^,,', { plain = true })) local result = {} vim.list_extend(result, vim.split(left, ',')) @@ -508,22 +531,20 @@ local to_lua_value = { assert(info.flaglist, 'That is the only one I know how to handle') + local result = {} --- @type table + if info.flaglist and info.commalist then local split_value = vim.split(value, ',') - local result = {} for _, v in ipairs(split_value) do result[v] = true end - - return result else - local result = {} for i = 1, #value do result[value:sub(i, i)] = true end - - return result end + + return result end, map = function(info, raw_value) @@ -533,10 +554,11 @@ local to_lua_value = { assert(info.commalist, 'Only commas are supported currently') - local result = {} + local result = {} --- @type table local comma_split = vim.split(raw_value, ',') for _, key_value_str in ipairs(comma_split) do + --- @type string, string local key, value = unpack(vim.split(key_value_str, ':')) key = vim.trim(key) @@ -582,14 +604,21 @@ local function prepend_value(info, current, new) end local add_methods = { + --- @param left integer + --- @param right integer number = function(left, right) return left + right end, + --- @param left string + --- @param right string string = function(left, right) return left .. right end, + --- @param left string[] + --- @param right string[] + --- @return string[] array = function(left, right) for _, v in ipairs(right) do table.insert(left, v) @@ -610,6 +639,8 @@ local function add_value(info, current, new) ) end +--- @param t table +--- @param val any local function remove_one_item(t, val) if vim.tbl_islist(t) then local remove_index = nil @@ -628,6 +659,8 @@ local function remove_one_item(t, val) end local remove_methods = { + --- @param left integer + --- @param right integer number = function(left, right) return left - right end, @@ -636,6 +669,9 @@ local remove_methods = { error('Subtraction not supported for strings.') end, + --- @param left string[] + --- @param right string[] + --- @return string[] array = function(left, right) if type(right) == 'string' then remove_one_item(left, right) diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index a47b35e991..28a531707f 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -152,25 +152,25 @@ end --- --- Path to begin searching from. If --- omitted, the |current-directory| is used. ---- @field path string +--- @field path? string --- --- Search upward through parent directories. --- Otherwise, search through child directories (recursively). --- (default: `false`) ---- @field upward boolean +--- @field upward? boolean --- --- Stop searching when this directory is reached. --- The directory itself is not searched. ---- @field stop string +--- @field stop? string --- --- Find only items of the given type. --- If omitted, all items that match {names} are included. ---- @field type string +--- @field type? string --- --- Stop the search after finding this many matches. --- Use `math.huge` to place no limit on the number of matches. --- (default: `1`) ---- @field limit number +--- @field limit? number --- Find files or directories (or other items as specified by `opts.type`) in the given path. --- @@ -229,7 +229,7 @@ function M.find(names, opts) names = { names } end - local path = opts.path or vim.uv.cwd() + local path = opts.path or assert(vim.uv.cwd()) local stop = opts.stop local limit = opts.limit or 1 diff --git a/runtime/lua/vim/loader.lua b/runtime/lua/vim/loader.lua index 0d708ca1eb..d3d8948654 100644 --- a/runtime/lua/vim/loader.lua +++ b/runtime/lua/vim/loader.lua @@ -7,7 +7,7 @@ local loaders = package.loaders local M = {} ----@alias CacheHash {mtime: {nsec: integer, sec: integer}, size: integer, type?: uv.aliases.fs_stat_types} +---@alias CacheHash {mtime: {nsec: integer, sec: integer}, size: integer, type?: string} ---@alias CacheEntry {hash:CacheHash, chunk:string} --- @class vim.loader.find.Opts diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 18d7c8b13e..6e50b87dd5 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -592,7 +592,8 @@ function vim.spairs(t) if keys[i] then return keys[i], t[keys[i]] end - end + end, + t end --- Tests if `t` is an "array": a table indexed _only_ by integers (potentially non-contiguous). -- cgit From 3d2aeec68d6a03a07394eea154447166f6487078 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 6 Mar 2024 09:40:11 +0000 Subject: refactor(lua): more efficient vim.tbl_islist No need to run a full iteration of the table. Simply return false when the next key isn't what we expect. --- runtime/lua/vim/shared.lua | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 6e50b87dd5..561d9e3f1b 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -652,18 +652,21 @@ function vim.tbl_islist(t) return false end - local num_elem = vim.tbl_count(t) - - if num_elem == 0 then + if next(t) == nil then return getmetatable(t) ~= vim._empty_dict_mt - else - for i = 1, num_elem do - if t[i] == nil then - return false - end + end + + local j = 1 + for _ in + pairs(t--[[@as table]]) + do + if t[j] == nil then + return false end - return true + j = j + 1 end + + return true end --- Counts the number of non-nil values in table `t`. -- cgit From 8149bd089e15043576b1e6588babd9c121740f1a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sun, 3 Mar 2024 11:54:39 +0000 Subject: feat(lsp): report fswatch errors Resolves #27713 Co-authored-by: Tomasz N --- runtime/lua/vim/_watch.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_watch.lua b/runtime/lua/vim/_watch.lua index d199cf8e29..97c5481ad1 100644 --- a/runtime/lua/vim/_watch.lua +++ b/runtime/lua/vim/_watch.lua @@ -283,6 +283,17 @@ function M.fswatch(path, opts, callback) '/.git/', path, }, { + stderr = function(err, data) + if err then + error(err) + end + + if data and #vim.trim(data) > 0 then + vim.schedule(function() + vim.notify('fswatch: ' .. data, vim.log.levels.ERROR) + end) + end + end, stdout = function(err, data) if err then error(err) -- cgit From 3e016fa8d4f797345d55f6006c42026abedb6c4e Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 6 Mar 2024 10:43:43 +0000 Subject: fix(lsp): actually send diagnostic-tags back to the server Fixes #27318 --- runtime/lua/vim/lsp/diagnostic.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index e4620897ac..08cea13548 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -136,7 +136,7 @@ end --- @param diagnostic vim.Diagnostic --- @return lsp.DiagnosticTag[]? -local function tags_vim_to_vim(diagnostic) +local function tags_vim_to_lsp(diagnostic) if not diagnostic._tags then return end @@ -173,7 +173,7 @@ local function diagnostic_vim_to_lsp(diagnostics) message = diagnostic.message, source = diagnostic.source, code = diagnostic.code, - tags = tags_vim_to_vim(diagnostics), + tags = tags_vim_to_lsp(diagnostic), }, diagnostic.user_data and (diagnostic.user_data.lsp or {}) or {}) end, diagnostics) end -- cgit From 3c572a31a3bb7009b4ad8eac56da1458acae3b75 Mon Sep 17 00:00:00 2001 From: Yi Ming Date: Sat, 2 Mar 2024 14:29:41 +0000 Subject: docs(treesitter): fix ambiguous parameter description about `lang` --- runtime/lua/vim/treesitter.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 61c5d66958..7cfebd2c00 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -77,7 +77,7 @@ end --- If needed, this will create the parser. --- ---@param bufnr (integer|nil) Buffer the parser should be tied to (default: current buffer) ----@param lang (string|nil) Filetype of this parser (default: buffer filetype) +---@param lang (string|nil) Language of this parser (default: from buffer filetype) ---@param opts (table|nil) Options to pass to the created language tree --- ---@return vim.treesitter.LanguageTree object to use for parsing @@ -452,7 +452,7 @@ end --- ``` --- ---@param bufnr (integer|nil) Buffer to be highlighted (default: current buffer) ----@param lang (string|nil) Language of the parser (default: buffer filetype) +---@param lang (string|nil) Language of the parser (default: from buffer filetype) function M.start(bufnr, lang) bufnr = bufnr or api.nvim_get_current_buf() local parser = M.get_parser(bufnr, lang) @@ -480,8 +480,8 @@ end --- Can also be shown with `:InspectTree`. *:InspectTree* --- ---@param opts table|nil Optional options table with the following possible keys: ---- - lang (string|nil): The language of the source buffer. If omitted, the ---- filetype of the source buffer is used. +--- - lang (string|nil): The language of the source buffer. If omitted, detect +--- from the filetype of the source buffer. --- - bufnr (integer|nil): Buffer to draw the tree into. If omitted, a new --- buffer is created. --- - winid (integer|nil): Window id to display the tree buffer in. If omitted, -- cgit From 85b13751a5fc28fadbe74d72982325ca27b4c775 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 6 Mar 2024 12:15:25 +0000 Subject: refactor(types): more fixes (2) --- runtime/lua/vim/iter.lua | 92 ++++++++++++++-------------- runtime/lua/vim/lsp/_dynamic.lua | 2 +- runtime/lua/vim/lsp/buf.lua | 7 +++ runtime/lua/vim/lsp/handlers.lua | 77 ++++++++++++----------- runtime/lua/vim/treesitter/_meta.lua | 7 +-- runtime/lua/vim/treesitter/_query_linter.lua | 8 +-- runtime/lua/vim/treesitter/languagetree.lua | 3 +- runtime/lua/vim/version.lua | 2 +- 8 files changed, 106 insertions(+), 92 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index 09de969b5b..77c8d1d170 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -64,6 +64,9 @@ --- In addition to the |vim.iter()| function, the |vim.iter| module provides --- convenience functions like |vim.iter.filter()| and |vim.iter.totable()|. +--- LuaLS is bad at generics which this module mostly deals with +--- @diagnostic disable:no-unknown + ---@nodoc ---@class IterMod ---@operator call:Iter @@ -189,7 +192,7 @@ end --- in the pipeline and returns false or nil if the --- current iterator element should be removed. ---@return Iter -function Iter.filter(self, f) +function Iter:filter(f) return self:map(function(...) if f(...) then return ... @@ -198,7 +201,7 @@ function Iter.filter(self, f) end ---@private -function ListIter.filter(self, f) +function ListIter:filter(f) local inc = self._head < self._tail and 1 or -1 local n = self._head for i = self._head, self._tail - inc, inc do @@ -231,12 +234,13 @@ end ---@param depth? number Depth to which |list-iterator| should be flattened --- (defaults to 1) ---@return Iter -function Iter.flatten(self, depth) -- luacheck: no unused args +---@diagnostic disable-next-line:unused-local +function Iter:flatten(depth) -- luacheck: no unused args error('flatten() requires a list-like table') end ---@private -function ListIter.flatten(self, depth) +function ListIter:flatten(depth) depth = depth or 1 local inc = self._head < self._tail and 1 or -1 local target = {} @@ -282,7 +286,7 @@ end --- in the next pipeline stage. Nil return values --- are filtered from the output. ---@return Iter -function Iter.map(self, f) +function Iter:map(f) -- Implementation note: the reader may be forgiven for observing that this -- function appears excessively convoluted. The problem to solve is that each -- stage of the iterator pipeline can return any number of values, and the @@ -326,7 +330,7 @@ function Iter.map(self, f) end ---@private -function ListIter.map(self, f) +function ListIter:map(f) local inc = self._head < self._tail and 1 or -1 local n = self._head for i = self._head, self._tail - inc, inc do @@ -347,7 +351,7 @@ end ---@param f fun(...) Function to execute for each item in the pipeline. --- Takes all of the values returned by the previous stage --- in the pipeline as arguments. -function Iter.each(self, f) +function Iter:each(f) local function fn(...) if select(1, ...) ~= nil then f(...) @@ -359,7 +363,7 @@ function Iter.each(self, f) end ---@private -function ListIter.each(self, f) +function ListIter:each(f) local inc = self._head < self._tail and 1 or -1 for i = self._head, self._tail - inc, inc do f(unpack(self._table[i])) @@ -392,7 +396,7 @@ end --- --- ---@return table -function Iter.totable(self) +function Iter:totable() local t = {} while true do @@ -407,7 +411,7 @@ function Iter.totable(self) end ---@private -function ListIter.totable(self) +function ListIter:totable() if self.next ~= ListIter.next or self._head >= self._tail then return Iter.totable(self) end @@ -445,7 +449,7 @@ end --- --- @param delim string Delimiter --- @return string -function Iter.join(self, delim) +function Iter:join(delim) return table.concat(self:totable(), delim) end @@ -470,7 +474,7 @@ end ---@param init A Initial value of the accumulator. ---@param f fun(acc:A, ...):A Accumulation function. ---@return A -function Iter.fold(self, init, f) +function Iter:fold(init, f) local acc = init --- Use a closure to handle var args returned from iterator @@ -487,7 +491,7 @@ function Iter.fold(self, init, f) end ---@private -function ListIter.fold(self, init, f) +function ListIter:fold(init, f) local acc = init local inc = self._head < self._tail and 1 or -1 for i = self._head, self._tail - inc, inc do @@ -513,14 +517,13 @@ end --- ``` --- ---@return any ----@diagnostic disable-next-line: unused-local -function Iter.next(self) -- luacheck: no unused args +function Iter:next() -- This function is provided by the source iterator in Iter.new. This definition exists only for -- the docstring end ---@private -function ListIter.next(self) +function ListIter:next() if self._head ~= self._tail then local v = self._table[self._head] local inc = self._head < self._tail and 1 or -1 @@ -542,12 +545,12 @@ end --- ``` --- ---@return Iter -function Iter.rev(self) -- luacheck: no unused args +function Iter:rev() error('rev() requires a list-like table') end ---@private -function ListIter.rev(self) +function ListIter:rev() local inc = self._head < self._tail and 1 or -1 self._head, self._tail = self._tail - inc, self._head - inc return self @@ -570,13 +573,12 @@ end --- ``` --- ---@return any ----@diagnostic disable-next-line: unused-local -function Iter.peek(self) -- luacheck: no unused args +function Iter:peek() error('peek() requires a list-like table') end ---@private -function ListIter.peek(self) +function ListIter:peek() if self._head ~= self._tail then return self._table[self._head] end @@ -605,7 +607,7 @@ end --- ``` ---@param f any ---@return any -function Iter.find(self, f) +function Iter:find(f) if type(f) ~= 'function' then local val = f f = function(v) @@ -652,12 +654,12 @@ end ---@param f any ---@return any ---@diagnostic disable-next-line: unused-local -function Iter.rfind(self, f) -- luacheck: no unused args +function Iter:rfind(f) -- luacheck: no unused args error('rfind() requires a list-like table') end ---@private -function ListIter.rfind(self, f) +function ListIter:rfind(f) if type(f) ~= 'function' then local val = f f = function(v) @@ -692,7 +694,7 @@ end --- ---@param n integer ---@return Iter -function Iter.take(self, n) +function Iter:take(n) local next = self.next local i = 0 self.next = function() @@ -705,7 +707,7 @@ function Iter.take(self, n) end ---@private -function ListIter.take(self, n) +function ListIter:take(n) local inc = self._head < self._tail and 1 or -1 self._tail = math.min(self._tail, self._head + n * inc) return self @@ -724,13 +726,12 @@ end --- ``` --- ---@return any ----@diagnostic disable-next-line: unused-local -function Iter.nextback(self) -- luacheck: no unused args +function Iter:nextback() error('nextback() requires a list-like table') end --- @nodoc -function ListIter.nextback(self) +function ListIter:nextback() if self._head ~= self._tail then local inc = self._head < self._tail and 1 or -1 self._tail = self._tail - inc @@ -755,13 +756,12 @@ end --- ``` --- ---@return any ----@diagnostic disable-next-line: unused-local -function Iter.peekback(self) -- luacheck: no unused args +function Iter:peekback() error('peekback() requires a list-like table') end ---@nodoc -function ListIter.peekback(self) +function ListIter:peekback() if self._head ~= self._tail then local inc = self._head < self._tail and 1 or -1 return self._table[self._tail - inc] @@ -782,7 +782,7 @@ end --- ---@param n number Number of values to skip. ---@return Iter -function Iter.skip(self, n) +function Iter:skip(n) for _ = 1, n do local _ = self:next() end @@ -790,7 +790,7 @@ function Iter.skip(self, n) end ---@private -function ListIter.skip(self, n) +function ListIter:skip(n) local inc = self._head < self._tail and n or -n self._head = self._head + inc if (inc > 0 and self._head > self._tail) or (inc < 0 and self._head < self._tail) then @@ -814,12 +814,12 @@ end ---@param n number Number of values to skip. ---@return Iter ---@diagnostic disable-next-line: unused-local -function Iter.skipback(self, n) -- luacheck: no unused args +function Iter:skipback(n) -- luacheck: no unused args error('skipback() requires a list-like table') end ---@private -function ListIter.skipback(self, n) +function ListIter:skipback(n) local inc = self._head < self._tail and n or -n self._tail = self._tail - inc if (inc > 0 and self._head > self._tail) or (inc < 0 and self._head < self._tail) then @@ -844,7 +844,7 @@ end --- ---@param n number The index of the value to return. ---@return any -function Iter.nth(self, n) +function Iter:nth(n) if n > 0 then return self:skip(n - 1):next() end @@ -866,7 +866,7 @@ end --- ---@param n number The index of the value to return. ---@return any -function Iter.nthback(self, n) +function Iter:nthback(n) if n > 0 then return self:skipback(n - 1):nextback() end @@ -880,12 +880,12 @@ end ---@param last number ---@return Iter ---@diagnostic disable-next-line: unused-local -function Iter.slice(self, first, last) -- luacheck: no unused args +function Iter:slice(first, last) -- luacheck: no unused args error('slice() requires a list-like table') end ---@private -function ListIter.slice(self, first, last) +function ListIter:slice(first, last) return self:skip(math.max(0, first - 1)):skipback(math.max(0, self._tail - last - 1)) end @@ -894,7 +894,7 @@ end ---@param pred fun(...):boolean Predicate function. Takes all values returned from the previous --- stage in the pipeline as arguments and returns true if the --- predicate matches. -function Iter.any(self, pred) +function Iter:any(pred) local any = false --- Use a closure to handle var args returned from iterator @@ -918,7 +918,7 @@ end ---@param pred fun(...):boolean Predicate function. Takes all values returned from the previous --- stage in the pipeline as arguments and returns true if the --- predicate matches. -function Iter.all(self, pred) +function Iter:all(pred) local all = true local function fn(...) @@ -953,7 +953,7 @@ end --- ``` --- ---@return any -function Iter.last(self) +function Iter:last() local last = self:next() local cur = self:next() while cur do @@ -964,7 +964,7 @@ function Iter.last(self) end ---@private -function ListIter.last(self) +function ListIter:last() local inc = self._head < self._tail and 1 or -1 local v = self._table[self._tail - inc] self._head = self._tail @@ -1000,7 +1000,7 @@ end --- ``` --- ---@return Iter -function Iter.enumerate(self) +function Iter:enumerate() local i = 0 return self:map(function(...) i = i + 1 @@ -1009,7 +1009,7 @@ function Iter.enumerate(self) end ---@private -function ListIter.enumerate(self) +function ListIter:enumerate() local inc = self._head < self._tail and 1 or -1 for i = self._head, self._tail - inc, inc do local v = self._table[i] diff --git a/runtime/lua/vim/lsp/_dynamic.lua b/runtime/lua/vim/lsp/_dynamic.lua index 9c2af979fa..819b03a63a 100644 --- a/runtime/lua/vim/lsp/_dynamic.lua +++ b/runtime/lua/vim/lsp/_dynamic.lua @@ -58,7 +58,7 @@ end --- @param method string --- @param opts? {bufnr: integer?} --- @return lsp.Registration? (table|nil) the registration if found ---- @private +--- @package function M:get(method, opts) opts = opts or {} opts.bufnr = opts.bufnr or vim.api.nvim_get_current_buf() diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 377c8680c7..fd78a10672 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -248,6 +248,9 @@ function M.format(options) vim.notify('[LSP] Format request failed, no matching language servers.') end + --- @param client vim.lsp.Client + --- @param params lsp.DocumentFormattingParams + --- @return lsp.DocumentFormattingParams local function set_range(client, params) if range then local range_params = @@ -294,6 +297,9 @@ end --- Restrict clients used for rename to ones where client.name matches --- this field. --- @field name? string +--- +--- (default: current buffer) +--- @field bufnr? integer --- Renames all references to the symbol under the cursor. --- @@ -786,6 +792,7 @@ function M.code_action(options) options = options or {} -- Detect old API call code_action(context) which should now be -- code_action({ context = context} ) + --- @diagnostic disable-next-line:undefined-field if options.diagnostics or options.only then options = { options = options } end diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index d816fb1482..daf4fec8d2 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -16,12 +16,12 @@ local function err_message(...) api.nvim_command('redraw') end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand M[ms.workspace_executeCommand] = function(_, _, _, _) -- Error handling is done implicitly by wrapping all handlers; see end of this file end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#progress +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#progress ---@param result lsp.ProgressParams ---@param ctx lsp.HandlerContext M[ms.dollar_progress] = function(_, result, ctx) @@ -57,7 +57,7 @@ M[ms.dollar_progress] = function(_, result, ctx) }) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_workDoneProgress_create +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_workDoneProgress_create ---@param result lsp.WorkDoneProgressCreateParams ---@param ctx lsp.HandlerContext M[ms.window_workDoneProgress_create] = function(_, result, ctx) @@ -70,7 +70,7 @@ M[ms.window_workDoneProgress_create] = function(_, result, ctx) return vim.NIL end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessageRequest +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessageRequest ---@param result lsp.ShowMessageRequestParams M[ms.window_showMessageRequest] = function(_, result) local actions = result.actions or {} @@ -106,7 +106,8 @@ M[ms.window_showMessageRequest] = function(_, result) end end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability +--- @param result lsp.RegistrationParams M[ms.client_registerCapability] = function(_, result, ctx) local client_id = ctx.client_id local client = assert(vim.lsp.get_client_by_id(client_id)) @@ -136,7 +137,8 @@ M[ms.client_registerCapability] = function(_, result, ctx) return vim.NIL end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_unregisterCapability +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_unregisterCapability +--- @param result lsp.UnregistrationParams M[ms.client_unregisterCapability] = function(_, result, ctx) local client_id = ctx.client_id local client = assert(vim.lsp.get_client_by_id(client_id)) @@ -150,7 +152,7 @@ M[ms.client_unregisterCapability] = function(_, result, ctx) return vim.NIL end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit M[ms.workspace_applyEdit] = function(_, workspace_edit, ctx) assert( workspace_edit, @@ -178,7 +180,8 @@ local function lookup_section(table, section) return vim.tbl_get(table, unpack(keys)) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_configuration +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_configuration +--- @param result lsp.ConfigurationParams M[ms.workspace_configuration] = function(_, result, ctx) local client_id = ctx.client_id local client = vim.lsp.get_client_by_id(client_id) @@ -211,7 +214,7 @@ M[ms.workspace_configuration] = function(_, result, ctx) return response end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_workspaceFolders +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_workspaceFolders M[ms.workspace_workspaceFolders] = function(_, _, ctx) local client_id = ctx.client_id local client = vim.lsp.get_client_by_id(client_id) @@ -238,7 +241,7 @@ M[ms.textDocument_inlayHint] = function(...) return vim.lsp.inlay_hint.on_inlayhint(...) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references M[ms.textDocument_references] = function(_, result, ctx, config) if not result or vim.tbl_isempty(result) then vim.notify('No references found') @@ -296,7 +299,7 @@ local function response_to_list(map_result, entity, title_fn) end end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol M[ms.textDocument_documentSymbol] = response_to_list( util.symbols_to_items, 'document symbols', @@ -306,12 +309,12 @@ M[ms.textDocument_documentSymbol] = response_to_list( end ) ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_symbol +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_symbol M[ms.workspace_symbol] = response_to_list(util.symbols_to_items, 'symbols', function(ctx) return string.format("Symbols matching '%s'", ctx.params.query) end) ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename M[ms.textDocument_rename] = function(_, result, ctx, _) if not result then vim.notify("Language server couldn't provide rename result", vim.log.levels.INFO) @@ -321,7 +324,7 @@ M[ms.textDocument_rename] = function(_, result, ctx, _) util.apply_workspace_edit(result, client.offset_encoding) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting M[ms.textDocument_rangeFormatting] = function(_, result, ctx, _) if not result then return @@ -330,7 +333,7 @@ M[ms.textDocument_rangeFormatting] = function(_, result, ctx, _) util.apply_text_edits(result, ctx.bufnr, client.offset_encoding) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting M[ms.textDocument_formatting] = function(_, result, ctx, _) if not result then return @@ -339,7 +342,7 @@ M[ms.textDocument_formatting] = function(_, result, ctx, _) util.apply_text_edits(result, ctx.bufnr, client.offset_encoding) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion M[ms.textDocument_completion] = function(_, result, _, _) if vim.tbl_isempty(result or {}) then return @@ -405,14 +408,14 @@ function M.hover(_, result, ctx, config) return util.open_floating_preview(contents, format, config) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover M[ms.textDocument_hover] = M.hover --- Jumps to a location. Used as a handler for multiple LSP methods. ---@param _ nil not used ---@param result (table) result of LSP method; a location or a list of locations. ---@param ctx (lsp.HandlerContext) table containing the context of the request, including the method ----@param config? vim.lsp.buf.LocationOpts +---@param config? vim.lsp.LocationOpts ---(`textDocument/definition` can return `Location` or `Location[]` local function location_handler(_, result, ctx, config) if result == nil or vim.tbl_isempty(result) then @@ -445,13 +448,13 @@ local function location_handler(_, result, ctx, config) api.nvim_command('botright copen') end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_declaration +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_declaration M[ms.textDocument_declaration] = location_handler ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition M[ms.textDocument_definition] = location_handler ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_typeDefinition +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_typeDefinition M[ms.textDocument_typeDefinition] = location_handler ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_implementation +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_implementation M[ms.textDocument_implementation] = location_handler --- |lsp-handler| for the method "textDocument/signatureHelp". @@ -509,10 +512,10 @@ function M.signature_help(_, result, ctx, config) return fbuf, fwin end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp M[ms.textDocument_signatureHelp] = M.signature_help ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight M[ms.textDocument_documentHighlight] = function(_, result, ctx, _) if not result then return @@ -525,21 +528,22 @@ M[ms.textDocument_documentHighlight] = function(_, result, ctx, _) util.buf_highlight_references(ctx.bufnr, result, client.offset_encoding) end ----@private +--- @private --- --- Displays call hierarchy in the quickfix window. --- ----@param direction 'from'|'to' `"from"` for incoming calls and `"to"` for outgoing calls ----@return function ---- `CallHierarchyIncomingCall[]` if {direction} is `"from"`, ---- `CallHierarchyOutgoingCall[]` if {direction} is `"to"`, -local make_call_hierarchy_handler = function(direction) +--- @param direction 'from'|'to' `"from"` for incoming calls and `"to"` for outgoing calls +--- @overload fun(direction:'from'): fun(_, result: lsp.CallHierarchyIncomingCall[]?) +--- @overload fun(direction:'to'): fun(_, result: lsp.CallHierarchyOutgoingCall[]?) +local function make_call_hierarchy_handler(direction) + --- @param result lsp.CallHierarchyIncomingCall[]|lsp.CallHierarchyOutgoingCall[] return function(_, result) if not result then return end local items = {} for _, call_hierarchy_call in pairs(result) do + --- @type lsp.CallHierarchyItem local call_hierarchy_item = call_hierarchy_call[direction] for _, range in pairs(call_hierarchy_call.fromRanges) do table.insert(items, { @@ -555,13 +559,14 @@ local make_call_hierarchy_handler = function(direction) end end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_incomingCalls +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_incomingCalls M[ms.callHierarchy_incomingCalls] = make_call_hierarchy_handler('from') ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_outgoingCalls +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_outgoingCalls M[ms.callHierarchy_outgoingCalls] = make_call_hierarchy_handler('to') ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_logMessage +--- @see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_logMessage +--- @param result lsp.LogMessageParams M[ms.window_logMessage] = function(_, result, ctx, _) local message_type = result.type local message = result.message @@ -583,7 +588,8 @@ M[ms.window_logMessage] = function(_, result, ctx, _) return result end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessage +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessage +--- @param result lsp.ShowMessageParams M[ms.window_showMessage] = function(_, result, ctx, _) local message_type = result.type local message = result.message @@ -602,7 +608,8 @@ M[ms.window_showMessage] = function(_, result, ctx, _) return result end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showDocument +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showDocument +--- @param result lsp.ShowDocumentParams M[ms.window_showDocument] = function(_, result, ctx, _) local uri = result.uri diff --git a/runtime/lua/vim/treesitter/_meta.lua b/runtime/lua/vim/treesitter/_meta.lua index 0b285d2d7f..19d97d2820 100644 --- a/runtime/lua/vim/treesitter/_meta.lua +++ b/runtime/lua/vim/treesitter/_meta.lua @@ -39,7 +39,7 @@ local TSNode = {} ---@param start? integer ---@param end_? integer ---@param opts? table ----@return fun(): integer, TSNode, TSMatch +---@return fun(): integer, TSNode, vim.treesitter.query.TSMatch function TSNode:_rawquery(query, captures, start, end_, opts) end ---@param query TSQuery @@ -47,14 +47,13 @@ function TSNode:_rawquery(query, captures, start, end_, opts) end ---@param start? integer ---@param end_? integer ---@param opts? table ----@return fun(): integer, TSMatch +---@return fun(): integer, vim.treesitter.query.TSMatch function TSNode:_rawquery(query, captures, start, end_, opts) end ---@alias TSLoggerCallback fun(logtype: 'parse'|'lex', msg: string) ---@class TSParser: userdata ----@field parse fun(self: TSParser, tree: TSTree?, source: integer|string, include_bytes: true): TSTree, Range6[] ----@field parse fun(self: TSParser, tree: TSTree?, source: integer|string, include_bytes: false|nil): TSTree, Range4[] +---@field parse fun(self: TSParser, tree: TSTree?, source: integer|string, include_bytes: boolean): TSTree, (Range4|Range6)[] ---@field reset fun(self: TSParser) ---@field included_ranges fun(self: TSParser, include_bytes: boolean?): integer[] ---@field set_included_ranges fun(self: TSParser, ranges: (Range6|TSNode)[]) diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua index b91e8ac38d..6216d4e891 100644 --- a/runtime/lua/vim/treesitter/_query_linter.lua +++ b/runtime/lua/vim/treesitter/_query_linter.lua @@ -17,7 +17,7 @@ local M = {} --- @field is_first_lang boolean Whether this is the first language of a linter run checking queries for multiple `langs` --- Adds a diagnostic for node in the query buffer ---- @param diagnostics Diagnostic[] +--- @param diagnostics vim.Diagnostic[] --- @param range Range4 --- @param lint string --- @param lang string? @@ -114,7 +114,7 @@ end --- @return vim.treesitter.ParseError? local parse = vim.func._memoize(hash_parse, function(node, buf, lang) local query_text = vim.treesitter.get_node_text(node, buf) - local ok, err = pcall(vim.treesitter.query.parse, lang, query_text) ---@type boolean|vim.treesitter.ParseError, string|Query + local ok, err = pcall(vim.treesitter.query.parse, lang, query_text) ---@type boolean|vim.treesitter.ParseError, string|vim.treesitter.Query if not ok and type(err) == 'string' then return get_error_entry(err, node) @@ -123,9 +123,9 @@ end) --- @param buf integer --- @param match vim.treesitter.query.TSMatch ---- @param query Query +--- @param query vim.treesitter.Query --- @param lang_context QueryLinterLanguageContext ---- @param diagnostics Diagnostic[] +--- @param diagnostics vim.Diagnostic[] local function lint_match(buf, match, query, lang_context, diagnostics) local lang = lang_context.lang local parser_info = lang_context.parser_info diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 2f1aa36d18..640477eed4 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -72,7 +72,7 @@ local TSCallbackNames = { ---@field private _callbacks table Callback handlers ---@field package _callbacks_rec table Callback handlers (recursive) ---@field private _children table Injected languages ----@field private _injection_query Query Queries defining injected languages +---@field private _injection_query vim.treesitter.Query Queries defining injected languages ---@field private _injections_processed boolean ---@field private _opts table Options ---@field private _parser TSParser Parser for language @@ -473,6 +473,7 @@ function LanguageTree:for_each_child(fn, include_self) end for _, child in pairs(self._children) do + --- @diagnostic disable-next-line:deprecated child:for_each_child(fn, true) end end diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua index f97e81273e..cd8748ede7 100644 --- a/runtime/lua/vim/version.lua +++ b/runtime/lua/vim/version.lua @@ -274,7 +274,7 @@ end --- @see # https://github.com/npm/node-semver#ranges --- --- @param spec string Version range "spec" ---- @return vim.VersionRange +--- @return vim.VersionRange? function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim if spec == '*' or spec == '' then return setmetatable({ from = M.parse('0.0.0') }, { __index = VersionRange }) -- cgit From 191cca2566a8afe2b2f2744f3eb763d810cc416c Mon Sep 17 00:00:00 2001 From: Will Hopkins Date: Sat, 2 Mar 2024 14:39:25 -0800 Subject: fix(types): move type annotation for `IterMod` --- runtime/lua/vim/iter.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index 77c8d1d170..357dd35bdc 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -1140,9 +1140,8 @@ function M.map(f, src, ...) return Iter.new(src, ...):map(f):totable() end ----@type IterMod return setmetatable(M, { __call = function(_, ...) return Iter.new(...) end, -}) +}) --[[@as IterMod]] -- cgit From 0101bdaa1ad8b09ebd5ef5551faf077f39be238c Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Mon, 19 Feb 2024 18:28:07 -0800 Subject: docs(lsp): nits and typos in client.lua --- runtime/lua/vim/lsp/client.lua | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index 6dd898bea7..d0054e073c 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -156,7 +156,7 @@ local validate = vim.validate --- @field handlers table --- --- The current pending requests in flight to the server. Entries are key-value ---- pairs with the key being the request ID while the value is a table with +--- pairs with the key being the request id while the value is a table with --- `type`, `bufnr`, and `method` key-value pairs. `type` is either "pending" --- for an active request, or "cancel" for a cancel request. It will be --- "complete" ephemerally while executing |LspRequest| autocmds when replies @@ -167,8 +167,8 @@ local validate = vim.validate --- to |vim.lsp.start_client()|. --- @field config vim.lsp.ClientConfig --- ---- Response from the server sent on ---- initialize` describing the server's capabilities. +--- Response from the server sent on `initialize` describing the server's +--- capabilities. --- @field server_capabilities lsp.ServerCapabilities? --- --- A ring buffer (|vim.ringbuf()|) containing progress messages @@ -217,10 +217,11 @@ local validate = vim.validate --- Sends a request to the server. --- This is a thin wrapper around {client.rpc.request} with some additional --- checking. ---- If {handler} is not specified, If one is not found there, then an error ---- will occur. Returns: {status}, {[client_id]}. {status} is a boolean ---- indicating if the notification was successful. If it is `false`, then it ---- will always be `false` (the client has shutdown). +--- If {handler} is not specified and if there's no respective global +--- handler, then an error will occur. +--- Returns: {status}, {[client_id]}. {status} is a boolean indicating if +--- the notification was successful. If it is `false`, then it will always +--- be `false` (the client has shutdown). --- If {status} is `true`, the function returns {request_id} as the second --- result. You can use this with `client.cancel_request(request_id)` to cancel --- the request. -- cgit From ae5095cac9b233cfb6785534de6f084c70dc6424 Mon Sep 17 00:00:00 2001 From: altermo <107814000+altermo@users.noreply.github.com> Date: Wed, 6 Mar 2024 17:18:00 +0100 Subject: fix(fs): use generics for better typing --- runtime/lua/vim/fs.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index 28a531707f..f9fe122f01 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -39,8 +39,9 @@ end --- Return the parent directory of the given path --- ----@param file (string) Path ----@return string|nil Parent directory of {file} +---@generic T : string|nil +---@param file T Path +---@return T Parent directory of {file} function M.dirname(file) if file == nil then return nil @@ -53,6 +54,7 @@ function M.dirname(file) elseif file == '/' or file:match('^/[^/]+$') then return '/' end + ---@type string local dir = file:match('[/\\]$') and file:sub(1, #file - 1) or file:match('^([/\\]?.+)[/\\]') if iswin and dir:match('^%w:$') then return dir .. '/' @@ -62,8 +64,9 @@ end --- Return the basename of the given path --- ----@param file string Path ----@return string|nil Basename of {file} +---@generic T : string|nil +---@param file T Path +---@return T Basename of {file} function M.basename(file) if file == nil then return nil -- cgit From 6525832a8c4d44a8ebabba02a5ea1ce09b389a4f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 7 Mar 2024 06:43:08 +0800 Subject: vim-patch:9.1.0155: can only get getregion() from current buffer (#27757) Problem: can only call getregion() for current buffer Solution: Allow to retrieve selections from different buffers (Shougo Matsushita) closes: vim/vim#14131 https://github.com/vim/vim/commit/84bf6e658da51126bdd2e50af1f40cabd149343f Co-authored-by: Shougo Matsushita --- runtime/lua/vim/_meta/vimfn.lua | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index ff95edddf6..3c72d8be1d 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -3525,11 +3525,13 @@ function vim.fn.getreg(regname, list) end --- @return table function vim.fn.getreginfo(regname) end ---- Returns the list of strings from {pos1} to {pos2} in current +--- Returns the list of strings from {pos1} to {pos2} from a --- buffer. --- --- {pos1} and {pos2} must both be |List|s with four numbers. ---- See |getpos()| for the format of the list. +--- See |getpos()| for the format of the list. It's possible +--- to specify positions from a different buffer, but please +--- note the limitations at |getregion-notes| --- --- The optional argument {opts} is a Dict and supports the --- following items: @@ -3550,6 +3552,7 @@ function vim.fn.getreginfo(regname) end --- This function is useful to get text starting and ending in --- different columns, such as a |charwise-visual| selection. --- +--- *getregion-notes* --- Note that: --- - Order of {pos1} and {pos2} doesn't matter, it will always --- return content from the upper left position to the lower @@ -3559,8 +3562,12 @@ function vim.fn.getreginfo(regname) end --- - If the region is blockwise and it starts or ends in the --- middle of a multi-cell character, it is not included but --- its selected part is substituted with spaces. ---- - If {pos1} or {pos2} is not current in the buffer, an empty +--- - If {pos1} and {pos2} are not in the same buffer, an empty --- list is returned. +--- - {pos1} and {pos2} must belong to a |bufloaded()| buffer. +--- - It is evaluated in current window context, this makes a +--- different if a buffer is displayed in a different window and +--- 'virtualedit' or 'list' is set --- --- Examples: > --- :xnoremap -- cgit From e52c25b7617ac6401b080f76b0e227161dfef230 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Sat, 2 Mar 2024 13:11:23 -0800 Subject: feat(lua): deprecate vim.tbl_add_reverse_lookup --- runtime/lua/vim/lsp.lua | 15 +++++----- runtime/lua/vim/lsp/log.lua | 26 +++++++++-------- runtime/lua/vim/lsp/protocol.lua | 60 +++++++++++++++++----------------------- runtime/lua/vim/lsp/rpc.lua | 9 ++++-- runtime/lua/vim/shared.lua | 3 ++ 5 files changed, 58 insertions(+), 55 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index ef5d9d7cff..d5c376ba44 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -146,9 +146,10 @@ end local client_errors_base = table.maxn(lsp.rpc.client_errors) local client_errors_offset = 0 -local function new_error_index() +local function client_error(name) client_errors_offset = client_errors_offset + 1 - return client_errors_base + client_errors_offset + local index = client_errors_base + client_errors_offset + return { [name] = index, [index] = name } end --- Error codes to be used with `on_error` from |vim.lsp.start_client|. @@ -158,12 +159,10 @@ end lsp.client_errors = tbl_extend( 'error', lsp.rpc.client_errors, - vim.tbl_add_reverse_lookup({ - BEFORE_INIT_CALLBACK_ERROR = new_error_index(), - ON_INIT_CALLBACK_ERROR = new_error_index(), - ON_ATTACH_ERROR = new_error_index(), - ON_EXIT_CALLBACK_ERROR = new_error_index(), - }) + client_error('BEFORE_INIT_CALLBACK_ERROR'), + client_error('ON_INIT_CALLBACK_ERROR'), + client_error('ON_ATTACH_ERROR'), + client_error('ON_EXIT_CALLBACK_ERROR') ) ---@private diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua index 018003bb81..9f2bd71158 100644 --- a/runtime/lua/vim/lsp/log.lua +++ b/runtime/lua/vim/lsp/log.lua @@ -2,16 +2,19 @@ local log = {} +local log_levels = vim.log.levels + --- 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", "OFF" --- Level numbers begin with "TRACE" at 0 +--- @type table --- @nodoc -log.levels = vim.deepcopy(vim.log.levels) +log.levels = vim.deepcopy(log_levels) -- Default log level is warn. -local current_log_level = log.levels.WARN +local current_log_level = log_levels.WARN local log_date_format = '%F %H:%M:%S' @@ -58,7 +61,7 @@ local function open_logfile() logfile, openerr = io.open(logfilename, 'a+') if not logfile then local err_msg = string.format('Failed to open LSP client log file: %s', openerr) - notify(err_msg, vim.log.levels.ERROR) + notify(err_msg, log_levels.ERROR) return false end @@ -77,12 +80,13 @@ local function open_logfile() return true end -for level, levelnr in pairs(log.levels) do +for level, levelnr in pairs(log_levels) do -- Also export the log level on the root object. log[level] = levelnr -end -vim.tbl_add_reverse_lookup(log.levels) + -- Add a reverse lookup. + log.levels[levelnr] = level +end --- @param level string --- @param levelnr integer @@ -123,19 +127,19 @@ end -- log at that level (if applicable, it is checked either way). --- @nodoc -log.debug = create_logger('DEBUG', vim.log.levels.DEBUG) +log.debug = create_logger('DEBUG', log_levels.DEBUG) --- @nodoc -log.error = create_logger('ERROR', vim.log.levels.ERROR) +log.error = create_logger('ERROR', log_levels.ERROR) --- @nodoc -log.info = create_logger('INFO', vim.log.levels.INFO) +log.info = create_logger('INFO', log_levels.INFO) --- @nodoc -log.trace = create_logger('TRACE', vim.log.levels.TRACE) +log.trace = create_logger('TRACE', log_levels.TRACE) --- @nodoc -log.warn = create_logger('WARN', vim.log.levels.WARN) +log.warn = create_logger('WARN', log_levels.WARN) --- Sets the current log level. ---@param level (string|integer) One of `vim.lsp.log.levels` diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 7016209372..599f02425e 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -1,22 +1,19 @@ --- @diagnostic disable: duplicate-doc-alias --- TODO(clason) can be simplified after reverse lookup is removed ----@param t table ----@return number[] -local function get_value_set(t) - local result = {} - for _, v in pairs(t) do - if type(v) == 'number' then - table.insert(result, v) - end +---@param tbl table +local function get_value_set(tbl) + local value_set = {} + for _, v in pairs(tbl) do + table.insert(value_set, v) end - table.sort(result) - return result + table.sort(value_set) + return value_set end -- Protocol for the Microsoft Language Server Protocol (mslsp) +local protocol = {} -local protocol = { +local constants = { --- @enum lsp.DiagnosticSeverity DiagnosticSeverity = { -- Reports an error. @@ -309,11 +306,13 @@ local protocol = { }, } --- TODO(mariasolos): Remove this reverse lookup. -for k, v in pairs(protocol) do - local tbl = vim.deepcopy(v, true) - vim.tbl_add_reverse_lookup(tbl) - protocol[k] = tbl +for k1, v1 in pairs(constants) do + local tbl = vim.deepcopy(v1, true) + for _, k2 in ipairs(vim.tbl_keys(tbl)) do + local v2 = tbl[k2] + tbl[v2] = k2 + end + protocol[k1] = tbl end --[=[ @@ -719,14 +718,7 @@ function protocol.make_client_capabilities() codeActionLiteralSupport = { codeActionKind = { - valueSet = (function() - local res = vim.iter.filter(function(value) - -- Filter out the keys that were added by the reverse lookup. - return value:match('^%l') - end, vim.tbl_values(protocol.CodeActionKind)) - table.sort(res) - return res - end)(), + valueSet = get_value_set(constants.CodeActionKind), }, }, isPreferredSupport = true, @@ -751,10 +743,10 @@ function protocol.make_client_capabilities() commitCharactersSupport = false, preselectSupport = false, deprecatedSupport = false, - documentationFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText }, + documentationFormat = { constants.MarkupKind.Markdown, constants.MarkupKind.PlainText }, }, completionItemKind = { - valueSet = get_value_set(protocol.CompletionItemKind), + valueSet = get_value_set(constants.CompletionItemKind), }, completionList = { itemDefaults = { @@ -783,13 +775,13 @@ function protocol.make_client_capabilities() }, hover = { dynamicRegistration = true, - contentFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText }, + contentFormat = { constants.MarkupKind.Markdown, constants.MarkupKind.PlainText }, }, signatureHelp = { dynamicRegistration = false, signatureInformation = { activeParameterSupport = true, - documentationFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText }, + documentationFormat = { constants.MarkupKind.Markdown, constants.MarkupKind.PlainText }, parameterInformation = { labelOffsetSupport = true, }, @@ -804,7 +796,7 @@ function protocol.make_client_capabilities() documentSymbol = { dynamicRegistration = false, symbolKind = { - valueSet = get_value_set(protocol.SymbolKind), + valueSet = get_value_set(constants.SymbolKind), }, hierarchicalDocumentSymbolSupport = true, }, @@ -815,7 +807,7 @@ function protocol.make_client_capabilities() publishDiagnostics = { relatedInformation = true, tagSupport = { - valueSet = get_value_set(protocol.DiagnosticTag), + valueSet = get_value_set(constants.DiagnosticTag), }, dataSupport = true, }, @@ -827,7 +819,7 @@ function protocol.make_client_capabilities() symbol = { dynamicRegistration = false, symbolKind = { - valueSet = get_value_set(protocol.SymbolKind), + valueSet = get_value_set(constants.SymbolKind), }, }, configuration = true, @@ -867,9 +859,9 @@ end --- Creates a normalized object describing LSP server capabilities. ---@param server_capabilities table Table of capabilities supported by the server ----@return lsp.ServerCapabilities|nil Normalized table of capabilities +---@return lsp.ServerCapabilities|nil : Normalized table of capabilities function protocol.resolve_capabilities(server_capabilities) - local TextDocumentSyncKind = protocol.TextDocumentSyncKind + local TextDocumentSyncKind = protocol.TextDocumentSyncKind ---@type table local textDocumentSync = server_capabilities.textDocumentSync if textDocumentSync == nil then -- Defaults if omitted. diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 8e014b1063..984e4f040a 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -130,7 +130,7 @@ local M = {} --- Mapping of error codes used by the client --- @nodoc -M.client_errors = { +local client_errors = { INVALID_SERVER_MESSAGE = 1, INVALID_SERVER_JSON = 2, NO_RESULT_CALLBACK_FOUND = 3, @@ -140,7 +140,12 @@ M.client_errors = { SERVER_RESULT_CALLBACK_ERROR = 7, } -M.client_errors = vim.tbl_add_reverse_lookup(M.client_errors) +--- @type table +--- @nodoc +M.client_errors = vim.deepcopy(client_errors) +for k, v in pairs(client_errors) do + M.client_errors[v] = k +end --- Constructs an error message from an LSP error object. --- diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 561d9e3f1b..bd553598c7 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -465,9 +465,12 @@ end --- `tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }` --- --- Note that this *modifies* the input. +---@deprecated ---@param o table Table to add the reverse to ---@return table o function vim.tbl_add_reverse_lookup(o) + vim.deprecate('vim.tbl_add_reverse_lookup', nil, '0.12') + --- @cast o table --- @type any[] local keys = vim.tbl_keys(o) -- cgit From 04232a19ccf0e49a3a19d0ef48221249d982b0d4 Mon Sep 17 00:00:00 2001 From: altermo <107814000+altermo@users.noreply.github.com> Date: Thu, 7 Mar 2024 09:16:05 +0100 Subject: fix(type): remove incorrect arguments from vim.rpc* --- runtime/lua/vim/_meta/builtin.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua index 4831989e1a..9a67667f02 100644 --- a/runtime/lua/vim/_meta/builtin.lua +++ b/runtime/lua/vim/_meta/builtin.lua @@ -91,9 +91,8 @@ function vim.empty_dict() end --- This function also works in a fast callback |lua-loop-callbacks|. --- @param channel integer --- @param method string ---- @param args? any[] --- @param ...? any -function vim.rpcnotify(channel, method, args, ...) end +function vim.rpcnotify(channel, method, ...) end --- Sends a request to {channel} to invoke {method} via |RPC| and blocks until --- a response is received. @@ -102,9 +101,8 @@ function vim.rpcnotify(channel, method, args, ...) end --- special value --- @param channel integer --- @param method string ---- @param args? any[] --- @param ...? any -function vim.rpcrequest(channel, method, args, ...) end +function vim.rpcrequest(channel, method, ...) end --- Compares strings case-insensitively. --- @param a string -- cgit From 5f3579e6ea12659d48e92b2126f83777908c28fc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 8 Mar 2024 06:44:57 +0800 Subject: vim-patch:9.1.0157: Duplicate assignment in f_getregion() (#27766) Problem: Duplicate assignment in f_getregion(). Solution: Remove the duplicate assignment. Also improve getregion() docs wording and fix an unrelated typo (zeertzjq) closes: vim/vim#14154 https://github.com/vim/vim/commit/0df8f93bdaea77a1afb9f4eca94fe67ec73e6df2 --- runtime/lua/vim/_meta/vimfn.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 3c72d8be1d..ac25547212 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -3531,7 +3531,7 @@ function vim.fn.getreginfo(regname) end --- {pos1} and {pos2} must both be |List|s with four numbers. --- See |getpos()| for the format of the list. It's possible --- to specify positions from a different buffer, but please ---- note the limitations at |getregion-notes| +--- note the limitations at |getregion-notes|. --- --- The optional argument {opts} is a Dict and supports the --- following items: @@ -3565,9 +3565,9 @@ function vim.fn.getreginfo(regname) end --- - If {pos1} and {pos2} are not in the same buffer, an empty --- list is returned. --- - {pos1} and {pos2} must belong to a |bufloaded()| buffer. ---- - It is evaluated in current window context, this makes a ---- different if a buffer is displayed in a different window and ---- 'virtualedit' or 'list' is set +--- - It is evaluated in current window context, which makes a +--- difference if the buffer is displayed in a window with +--- different 'virtualedit' or 'list' values. --- --- Examples: > --- :xnoremap -- cgit From d741e5d1629948876cf8bdcacf6c8bc8a4924f94 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 8 Mar 2024 06:52:14 +0800 Subject: vim-patch:9.1.0154: shm=F not respected when reloading buffer with 'autoread' Problem: shm=F not respected when reloading buffer with 'autoread' Solution: Check SHM_FILEINFO in buf_check_timestamp() (Shougo Matsushita) closes: vim/vim#14144 https://github.com/vim/vim/commit/9db39b0ec90600bb41faec3a12b934b17c298b1f Co-authored-by: Shougo Matsushita --- runtime/lua/vim/_meta/options.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 5a9215fa9e..757720d8fb 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -5799,7 +5799,8 @@ vim.bo.sw = vim.bo.shiftwidth --- items, for instance "scanning tags" --- q do not show "recording @a" when recording a macro *shm-q* --- F don't give the file info when editing a file, like *shm-F* ---- `:silent` was used for the command +--- `:silent` was used for the command; note that this also +--- affects messages from 'autoread' reloading --- S do not show search count message when searching, e.g. *shm-S* --- "[1/5]" --- -- cgit From 649dd00fe2e54183cc210f24d36504a61e5ea605 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Fri, 8 Mar 2024 11:23:17 +0100 Subject: feat!: remove deprecated functions --- runtime/lua/vim/_editor.lua | 6 ----- runtime/lua/vim/lsp/buf.lua | 10 -------- runtime/lua/vim/treesitter.lua | 42 --------------------------------- runtime/lua/vim/treesitter/language.lua | 10 -------- runtime/lua/vim/treesitter/query.lua | 40 ------------------------------- 5 files changed, 108 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index c588802193..b73fad6bfa 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -908,12 +908,6 @@ do end end ----@private -function vim.pretty_print(...) - vim.deprecate('vim.pretty_print()', 'vim.print()', '0.10') - return vim.print(...) -end - --- "Pretty prints" the given arguments and returns them unmodified. --- --- Example: diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index fd78a10672..50121f30b2 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -28,16 +28,6 @@ local function request(method, params, handler) return vim.lsp.buf_request(0, method, params, handler) end ---- Checks whether the language servers attached to the current buffer are ---- ready. ---- ----@return boolean : if server responds. ----@deprecated -function M.server_ready() - vim.deprecate('vim.lsp.buf.server_ready()', nil, '0.10') - return not not vim.lsp.buf_notify(0, 'window/progress', {}) -end - --- Displays hover information about the symbol under the cursor in a floating --- window. Calling the function twice will jump into the floating window. function M.hover() diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 7cfebd2c00..d1215885d8 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -391,48 +391,6 @@ function M.get_node(opts) return root_lang_tree:named_node_for_range(ts_range, opts) end ---- Returns the smallest named node at the given position ---- ----@param bufnr integer Buffer number (0 for current buffer) ----@param row integer Position row ----@param col integer Position column ----@param opts table Optional keyword arguments: ---- - lang string|nil Parser language ---- - ignore_injections boolean Ignore injected languages (default true) ---- ----@return TSNode | nil Node at the given position ----@deprecated -function M.get_node_at_pos(bufnr, row, col, opts) - vim.deprecate('vim.treesitter.get_node_at_pos()', 'vim.treesitter.get_node()', '0.10') - if bufnr == 0 then - bufnr = api.nvim_get_current_buf() - end - local ts_range = { row, col, row, col } - - opts = opts or {} - - local root_lang_tree = M.get_parser(bufnr, opts.lang) - if not root_lang_tree then - return - end - - return root_lang_tree:named_node_for_range(ts_range, opts) -end - ---- Returns the smallest named node under the cursor ---- ----@param winnr (integer|nil) Window handle or 0 for current window (default) ---- ----@return string Name of node under the cursor ----@deprecated -function M.get_node_at_cursor(winnr) - vim.deprecate('vim.treesitter.get_node_at_cursor()', 'vim.treesitter.get_node():type()', '0.10') - winnr = winnr or 0 - local bufnr = api.nvim_win_get_buf(winnr) - - return M.get_node({ bufnr = bufnr, ignore_injections = false }):type() -end - --- Starts treesitter highlighting for a buffer --- --- Can be used in an ftplugin or FileType autocommand. diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 78c73c698c..47abf65332 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -150,14 +150,4 @@ function M.inspect(lang) return vim._ts_inspect_language(lang) end ----@deprecated -function M.inspect_language(...) - vim.deprecate( - 'vim.treesitter.language.inspect_language()', - 'vim.treesitter.language.inspect()', - '0.10' - ) - return M.inspect(...) -end - return M diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 6c7f713fd7..85e477be58 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -84,16 +84,6 @@ local function add_included_lang(base_langs, lang, ilang) return false end ----@deprecated -function M.get_query_files(...) - vim.deprecate( - 'vim.treesitter.query.get_query_files()', - 'vim.treesitter.query.get_files()', - '0.10' - ) - return M.get_files(...) -end - --- Gets the list of files used to make up a query --- ---@param lang string Language to get query for @@ -204,12 +194,6 @@ local explicit_queries = setmetatable({}, { end, }) ----@deprecated -function M.set_query(...) - vim.deprecate('vim.treesitter.query.set_query()', 'vim.treesitter.query.set()', '0.10') - M.set(...) -end - --- Sets the runtime query named {query_name} for {lang} --- --- This allows users to override any runtime files and/or configuration @@ -222,12 +206,6 @@ function M.set(lang, query_name, text) explicit_queries[lang][query_name] = M.parse(lang, text) end ----@deprecated -function M.get_query(...) - vim.deprecate('vim.treesitter.query.get_query()', 'vim.treesitter.query.get()', '0.10') - return M.get(...) -end - --- Returns the runtime query {query_name} for {lang}. --- ---@param lang string Language to use for the query @@ -249,12 +227,6 @@ M.get = vim.func._memoize('concat-2', function(lang, query_name) return M.parse(lang, query_string) end) ----@deprecated -function M.parse_query(...) - vim.deprecate('vim.treesitter.query.parse_query()', 'vim.treesitter.query.parse()', '0.10') - return M.parse(...) -end - --- Parse {query} as a string. (If the query is in a file, the caller --- should read the contents into a string before calling). --- @@ -280,18 +252,6 @@ M.parse = vim.func._memoize('concat-2', function(lang, query) return Query.new(lang, ts_query) end) ----@deprecated -function M.get_range(...) - vim.deprecate('vim.treesitter.query.get_range()', 'vim.treesitter.get_range()', '0.10') - return vim.treesitter.get_range(...) -end - ----@deprecated -function M.get_node_text(...) - vim.deprecate('vim.treesitter.query.get_node_text()', 'vim.treesitter.get_node_text()', '0.10') - return vim.treesitter.get_node_text(...) -end - --- Implementations of predicates that can optionally be prefixed with "any-". --- --- These functions contain the implementations for each predicate, correctly -- cgit From ade1b12f49c3b3914c74847d791eb90ea90b56b7 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 8 Mar 2024 12:25:18 +0000 Subject: docs: support inline markdown - Tags are now created with `[tag]()` - References are now created with `[tag]` - Code spans are no longer wrapped --- runtime/lua/vim/_editor.lua | 2 +- runtime/lua/vim/_inspector.lua | 4 +- runtime/lua/vim/_meta/api.lua | 90 +++++++++++++++++------------ runtime/lua/vim/_options.lua | 4 +- runtime/lua/vim/diagnostic.lua | 4 +- runtime/lua/vim/iter.lua | 4 +- runtime/lua/vim/lsp/client.lua | 4 +- runtime/lua/vim/treesitter.lua | 4 +- runtime/lua/vim/treesitter/languagetree.lua | 6 +- runtime/lua/vim/treesitter/query.lua | 2 +- runtime/lua/vim/version.lua | 4 +- 11 files changed, 72 insertions(+), 56 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index b73fad6bfa..6cf77b4648 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -502,7 +502,7 @@ end ---@param bufnr integer Buffer number, or 0 for current buffer ---@param pos1 integer[]|string Start of region as a (line, column) tuple or |getpos()|-compatible string ---@param pos2 integer[]|string End of region as a (line, column) tuple or |getpos()|-compatible string ----@param regtype string \|setreg()|-style selection type +---@param regtype string [setreg()]-style selection type ---@param inclusive boolean Controls whether the ending column is inclusive (see also 'selection'). ---@return table region Dict of the form `{linenr = {startcol,endcol}}`. `endcol` is exclusive, and ---whole lines are returned as `{startcol,endcol} = {0,-1}`. diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua index 2999630fce..afbd6211cd 100644 --- a/runtime/lua/vim/_inspector.lua +++ b/runtime/lua/vim/_inspector.lua @@ -25,7 +25,7 @@ local defaults = { ---Get all the items at a given buffer position. --- ----Can also be pretty-printed with `:Inspect!`. *:Inspect!* +---Can also be pretty-printed with `:Inspect!`. [:Inspect!]() --- ---@param bufnr? integer defaults to the current buffer ---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor @@ -143,7 +143,7 @@ end ---Show all the items at a given buffer position. --- ----Can also be shown with `:Inspect`. *:Inspect* +---Can also be shown with `:Inspect`. [:Inspect]() --- ---@param bufnr? integer defaults to the current buffer ---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 94eab72291..cb4c8749b8 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -530,7 +530,7 @@ function vim.api.nvim_buf_line_count(buffer) end --- EOL of a line, continue the highlight for the rest of the --- screen line (just like for diff and cursorline highlight). --- • virt_text : virtual text to link to this mark. A list of ---- [text, highlight] tuples, each representing a text chunk +--- `[text, highlight]` tuples, each representing a text chunk --- with specified highlight. `highlight` element can either be --- a single highlight group, or an array of multiple highlight --- groups that will be stacked (highest priority last). A @@ -563,8 +563,8 @@ function vim.api.nvim_buf_line_count(buffer) end --- for "inline" virt_text. --- • virt_lines : virtual lines to add next to this mark This --- should be an array over lines, where each line in turn is an ---- array over [text, highlight] tuples. In general, buffer and ---- window options do not affect the display of the text. In +--- array over `[text, highlight]` tuples. In general, buffer +--- and window options do not affect the display of the text. In --- particular 'wrap' and 'linebreak' options do not take --- effect, so the number of extra screen lines will always --- match the size of the array. However the 'tabstop' buffer @@ -690,9 +690,9 @@ function vim.api.nvim_buf_set_option(buffer, name, value) end --- Indexing is zero-based. Row indices are end-inclusive, and column indices --- are end-exclusive. --- ---- To insert text at a given `(row, column)` location, use `start_row = ---- end_row = row` and `start_col = end_col = col`. To delete the text in a ---- range, use `replacement = {}`. +--- To insert text at a given `(row, column)` location, use +--- `start_row = end_row = row` and `start_col = end_col = col`. To delete the +--- text in a range, use `replacement = {}`. --- --- Prefer `nvim_buf_set_lines()` if you are only adding or deleting entire --- lines. @@ -903,9 +903,9 @@ function vim.api.nvim_create_augroup(name, opts) end --- • event: (string) name of the triggered event --- `autocmd-events` --- • group: (number|nil) autocommand group id, if any ---- • match: (string) expanded value of `` ---- • buf: (number) expanded value of `` ---- • file: (string) expanded value of `` +--- • match: (string) expanded value of +--- • buf: (number) expanded value of +--- • file: (string) expanded value of --- • data: (any) arbitrary data passed from --- `nvim_exec_autocmds()` --- • command (string) optional: Vim command to execute on event. @@ -960,22 +960,21 @@ function vim.api.nvim_create_namespace(name) end --- argument that contains the following keys: --- • name: (string) Command name --- • args: (string) The args passed to the command, if any ---- `` +--- --- • fargs: (table) The args split by unescaped whitespace ---- (when more than one argument is allowed), if any ---- `` +--- (when more than one argument is allowed), if any --- • nargs: (string) Number of arguments `:command-nargs` --- • bang: (boolean) "true" if the command was executed with a ---- ! modifier `` +--- ! modifier --- • line1: (number) The starting line of the command range ---- `` +--- --- • line2: (number) The final line of the command range ---- `` +--- --- • range: (number) The number of items in the command range: ---- 0, 1, or 2 `` ---- • count: (number) Any count supplied `` ---- • reg: (string) The optional register, if specified `` ---- • mods: (string) Command modifiers, if any `` +--- 0, 1, or 2 +--- • count: (number) Any count supplied +--- • reg: (string) The optional register, if specified +--- • mods: (string) Command modifiers, if any --- • smods: (table) Command modifiers in a structured format. --- Has the same structure as the "mods" key of --- `nvim_parse_cmd()`. @@ -1049,9 +1048,9 @@ function vim.api.nvim_del_var(name) end --- Echo a message. --- ---- @param chunks any[] A list of [text, hl_group] arrays, each representing a text ---- chunk with specified highlight. `hl_group` element can be ---- omitted for no highlight. +--- @param chunks any[] A list of `[text, hl_group]` arrays, each representing a +--- text chunk with specified highlight. `hl_group` element can +--- be omitted for no highlight. --- @param history boolean if true, add to `message-history`. --- @param opts vim.api.keyset.echo_opts Optional parameters. --- • verbose: Message was printed as a result of 'verbose' option @@ -1134,7 +1133,7 @@ function vim.api.nvim_exec2(src, opts) end --- • buffer (integer) optional: buffer number `autocmd-buflocal`. --- Cannot be used with {pattern}. --- • modeline (bool) optional: defaults to true. Process the ---- modeline after the autocommands ``. +--- modeline after the autocommands . --- • data (any): arbitrary data to send to the autocommand --- callback. See `nvim_create_autocmd()` for details. function vim.api.nvim_exec_autocmds(event, opts) end @@ -1541,7 +1540,7 @@ function vim.api.nvim_notify(msg, log_level, opts) end --- be to the pty master end. For instance, a carriage return is --- sent as a "\r", not as a "\n". `textlock` applies. It is --- possible to call `nvim_chan_send()` directly in the callback ---- however. ["input", term, bufnr, data] +--- however. `["input", term, bufnr, data]` --- • force_crlf: (boolean, default true) Convert "\n" to "\r\n". --- @return integer function vim.api.nvim_open_term(buffer, opts) end @@ -1625,9 +1624,9 @@ function vim.api.nvim_open_term(buffer, opts) end --- • width: Window width (in character cells). Minimum of 1. --- • height: Window height (in character cells). Minimum of 1. --- • bufpos: Places float relative to buffer text (only when ---- relative="win"). Takes a tuple of zero-indexed [line, ---- column]. `row` and `col` if given are applied relative to ---- this position, else they default to: +--- relative="win"). Takes a tuple of zero-indexed +--- `[line, column]`. `row` and `col` if given are applied +--- relative to this position, else they default to: --- • `row=1` and `col=0` if `anchor` is "NW" or "NE" --- • `row=0` and `col=0` if `anchor` is "SW" or "SE" (thus --- like a tooltip near the buffer text). @@ -1756,8 +1755,8 @@ function vim.api.nvim_parse_cmd(str, opts) end --- operator/space, though also yielding an error). --- • "l" when needing to start parsing with lvalues for ":let" --- or ":for". Common flag sets: ---- • "m" to parse like for ":echo". ---- • "E" to parse like for "=". +--- • "m" to parse like for `":echo"`. +--- • "E" to parse like for `"="`. --- • empty string for ":call". --- • "lm" to parse for ":let". --- @param highlight boolean If true, return value will also include "highlight" key @@ -1887,15 +1886,32 @@ function vim.api.nvim_set_current_win(window) end --- --- @param ns_id integer Namespace id from `nvim_create_namespace()` --- @param opts vim.api.keyset.set_decoration_provider Table of callbacks: ---- • on_start: called first on each screen redraw ["start", tick] +--- • on_start: called first on each screen redraw +--- ``` +--- ["start", tick] +--- ``` +--- --- • on_buf: called for each buffer being redrawn (before window ---- callbacks) ["buf", bufnr, tick] +--- callbacks) +--- ``` +--- ["buf", bufnr, tick] +--- ``` +--- --- • on_win: called when starting to redraw a specific window. ---- ["win", winid, bufnr, topline, botline] +--- ``` +--- ["win", winid, bufnr, topline, botline] +--- ``` +--- --- • on_line: called for each buffer line being redrawn. (The ---- interaction with fold lines is subject to change) ["line", ---- winid, bufnr, row] ---- • on_end: called at the end of a redraw cycle ["end", tick] +--- interaction with fold lines is subject to change) +--- ``` +--- ["line", winid, bufnr, row] +--- ``` +--- +--- • on_end: called at the end of a redraw cycle +--- ``` +--- ["end", tick] +--- ``` function vim.api.nvim_set_decoration_provider(ns_id, opts) end --- Sets a highlight group. @@ -1955,7 +1971,7 @@ function vim.api.nvim_set_hl_ns_fast(ns_id) end --- To set a buffer-local mapping, use `nvim_buf_set_keymap()`. --- --- Unlike `:map`, leading/trailing whitespace is accepted as part of the ---- {lhs} or {rhs}. Empty {rhs} is ``. `keycodes` are replaced as usual. +--- {lhs} or {rhs}. Empty {rhs} is . `keycodes` are replaced as usual. --- --- Example: --- @@ -1977,7 +1993,7 @@ function vim.api.nvim_set_hl_ns_fast(ns_id) end --- @param lhs string Left-hand-side `{lhs}` of the mapping. --- @param rhs string Right-hand-side `{rhs}` of the mapping. --- @param opts vim.api.keyset.keymap Optional parameters map: Accepts all `:map-arguments` as keys ---- except ``, values are booleans (default false). Also: +--- except , values are booleans (default false). Also: --- • "noremap" disables `recursive_mapping`, like `:noremap` --- • "desc" human-readable description. --- • "callback" Lua function called in place of {rhs}. diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua index 60dcf8c64a..13ad6cc58f 100644 --- a/runtime/lua/vim/_options.lua +++ b/runtime/lua/vim/_options.lua @@ -276,7 +276,7 @@ vim.go = setmetatable({}, { }) --- Get or set buffer-scoped |options| for the buffer with number {bufnr}. ---- If [{bufnr}] is omitted then the current buffer is used. +--- If {bufnr} is omitted then the current buffer is used. --- Invalid {bufnr} or key is an error. --- --- Note: this is equivalent to `:setlocal` for |global-local| options and `:set` otherwise. @@ -293,7 +293,7 @@ vim.bo = new_buf_opt_accessor() --- Get or set window-scoped |options| for the window with handle {winid} and --- buffer with number {bufnr}. Like `:setlocal` if setting a |global-local| option ---- or if {bufnr} is provided, like `:set` otherwise. If [{winid}] is omitted then +--- or if {bufnr} is provided, like `:set` otherwise. If {winid} is omitted then --- the current window is used. Invalid {winid}, {bufnr} or key is an error. --- --- Note: only {bufnr} with value `0` (the current buffer in the window) is diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 9483474a40..d5075d7d3d 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -2,7 +2,7 @@ local api, if_nil = vim.api, vim.F.if_nil local M = {} ---- *diagnostic-structure* +--- [diagnostic-structure]() --- --- Diagnostics use the same indexing as the rest of the Nvim API (i.e. 0-based --- rows and columns). |api-indexing| @@ -68,7 +68,7 @@ local M = {} --- --- Update diagnostics in Insert mode --- (if `false`, diagnostics are updated on |InsertLeave|) ---- (default: `false) +--- (default: `false`) --- @field update_in_insert? boolean --- --- Sort diagnostics by severity. This affects the order in which signs and diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index 357dd35bdc..a37b7f7858 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -1,7 +1,7 @@ --- @brief --- ---- \*vim.iter()\* is an interface for |iterable|s: it wraps a table or function argument into an ---- \*Iter\* object with methods (such as |Iter:filter()| and |Iter:map()|) that transform the +--- [vim.iter()]() is an interface for [iterable]s: it wraps a table or function argument into an +--- [Iter]() object with methods (such as [Iter:filter()] and [Iter:map()]) that transform the --- underlying source data. These methods can be chained to create iterator "pipelines": the output --- of each pipeline stage is input to the next stage. The first stage depends on the type passed to --- `vim.iter()`: diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index d0054e073c..ff0db166d5 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -219,7 +219,7 @@ local validate = vim.validate --- checking. --- If {handler} is not specified and if there's no respective global --- handler, then an error will occur. ---- Returns: {status}, {[client_id]}. {status} is a boolean indicating if +--- Returns: {status}, {client_id}?. {status} is a boolean indicating if --- the notification was successful. If it is `false`, then it will always --- be `false` (the client has shutdown). --- If {status} is `true`, the function returns {request_id} as the second @@ -262,7 +262,7 @@ local validate = vim.validate --- --- Checks if a client supports a given method. --- Always returns true for unknown off-spec methods. ---- [opts] is a optional `{bufnr?: integer}` table. +--- {opts} is a optional `{bufnr?: integer}` table. --- Some language server capabilities can be file specific. --- @field supports_method fun(method: string, opts?: {bufnr: integer?}): boolean --- diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index d1215885d8..a09619f369 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -432,10 +432,10 @@ end --- --- While in the window, press "a" to toggle display of anonymous nodes, "I" to toggle the --- display of the source language of each node, "o" to toggle the query editor, and press ---- to jump to the node under the cursor in the source buffer. Folding also works +--- [] to jump to the node under the cursor in the source buffer. Folding also works --- (try |zo|, |zc|, etc.). --- ---- Can also be shown with `:InspectTree`. *:InspectTree* +--- Can also be shown with `:InspectTree`. [:InspectTree]() --- ---@param opts table|nil Optional options table with the following possible keys: --- - lang (string|nil): The language of the source buffer. If omitted, detect diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 640477eed4..62714d3f1b 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -1,4 +1,4 @@ ---- @brief A \*LanguageTree\* contains a tree of parsers: the root treesitter parser for {lang} and +--- @brief A [LanguageTree]() contains a tree of parsers: the root treesitter parser for {lang} and --- any "injected" language parsers, which themselves may inject other languages, recursively. --- For example a Lua buffer containing some Vimscript commands needs multiple parsers to fully --- understand its contents. @@ -93,8 +93,8 @@ local LanguageTree = {} ---Optional arguments: ---@class vim.treesitter.LanguageTree.new.Opts ---@inlinedoc ----@field queries table -- Deprecated ----@field injections table +---@field queries? table -- Deprecated +---@field injections? table LanguageTree.__index = LanguageTree diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 85e477be58..a086f5e876 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -995,7 +995,7 @@ end --- Opens a live editor to query the buffer you started from. --- ---- Can also be shown with *:EditQuery*. +--- Can also be shown with [:EditQuery](). --- --- If you move the cursor to a capture name ("@foo"), text matching the capture is highlighted in --- the source buffer. The query editor is a scratch buffer, use `:write` to save it. You can find diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua index cd8748ede7..0b149700b5 100644 --- a/runtime/lua/vim/version.lua +++ b/runtime/lua/vim/version.lua @@ -12,9 +12,9 @@ --- end --- ``` --- ---- *vim.version()* returns the version of the current Nvim process. +--- [vim.version()]() returns the version of the current Nvim process. --- ---- VERSION RANGE SPEC *version-range* +--- VERSION RANGE SPEC [version-range]() --- --- A version "range spec" defines a semantic version range which can be tested against a version, --- using |vim.version.range()|. -- cgit