diff options
Diffstat (limited to 'runtime/lua')
-rw-r--r-- | runtime/lua/vim/_editor.lua | 66 | ||||
-rw-r--r-- | runtime/lua/vim/diagnostic.lua | 8 | ||||
-rw-r--r-- | runtime/lua/vim/filetype.lua | 40 | ||||
-rw-r--r-- | runtime/lua/vim/filetype/detect.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/keymap.lua | 26 | ||||
-rw-r--r-- | runtime/lua/vim/lsp.lua | 26 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/buf.lua | 99 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/handlers.lua | 52 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/protocol.lua | 1 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 24 |
10 files changed, 225 insertions, 119 deletions
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 442d7b07d8..b8a7f71145 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -288,6 +288,9 @@ end --- Execute Vim script commands. --- +--- Note that `vim.cmd` can be indexed with a command name to return a callable function to the +--- command. +--- --- Example: --- <pre> --- vim.cmd('echo 42') @@ -297,7 +300,23 @@ end --- autocmd FileType c setlocal cindent --- augroup END --- ]]) ---- vim.cmd({ cmd = 'echo', args = { '"foo"' } }) +--- +--- -- Ex command :echo "foo" +--- -- Note string literals need to be double quoted. +--- vim.cmd('echo "foo"') +--- vim.cmd { cmd = 'echo', args = { '"foo"' } } +--- vim.cmd.echo({ args = { '"foo"' } }) +--- vim.cmd.echo('"foo"') +--- +--- -- Ex command :write! myfile.txt +--- vim.cmd('write! myfile.txt') +--- vim.cmd { cmd = 'write', args = { "myfile.txt" }, bang = true } +--- vim.cmd.write { args = { "myfile.txt" }, bang = true } +--- vim.cmd.write { "myfile.txt", bang = true } +--- +--- -- Ex command :colorscheme blue +--- vim.cmd('colorscheme blue') +--- vim.cmd.colorscheme('blue') --- </pre> --- ---@param command string|table Command(s) to execute. @@ -307,14 +326,47 @@ end --- If a table, executes a single command. In this case, it is an alias --- to |nvim_cmd()| where `opts` is empty. ---@see |ex-cmd-index| -function vim.cmd(command) - if type(command) == 'table' then - return vim.api.nvim_cmd(command, {}) - else - return vim.api.nvim_exec(command, false) - end +function vim.cmd(command) -- luacheck: no unused + error(command) -- Stub for gen_vimdoc.py end +local VIM_CMD_ARG_MAX = 20 + +vim.cmd = setmetatable({}, { + __call = function(_, command) + if type(command) == 'table' then + return vim.api.nvim_cmd(command, {}) + else + return vim.api.nvim_exec(command, false) + end + end, + __index = function(t, command) + t[command] = function(...) + local opts + if select('#', ...) == 1 and type(select(1, ...)) == 'table' then + opts = select(1, ...) + + -- Move indexed positions in opts to opt.args + if opts[1] and not opts.args then + opts.args = {} + for i = 1, VIM_CMD_ARG_MAX do + if not opts[i] then + break + end + opts.args[i] = opts[i] + opts[i] = nil + end + end + else + opts = { args = { ... } } + end + opts.cmd = command + return vim.api.nvim_cmd(opts, {}) + end + return t[command] + end, +}) + -- These are the vim.env/v/g/o/bo/wo variable magic accessors. do local validate = vim.validate diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index ae20b5c517..3f71d4f70d 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -586,12 +586,12 @@ end --- --- For example, if a user enables virtual text globally with --- <pre> ---- vim.diagnostic.config({virtual_text = true}) +--- vim.diagnostic.config({ virtual_text = true }) --- </pre> --- --- and a diagnostic producer sets diagnostics with --- <pre> ---- vim.diagnostic.set(ns, 0, diagnostics, {virtual_text = false}) +--- vim.diagnostic.set(ns, 0, diagnostics, { virtual_text = false }) --- </pre> --- --- then virtual text will not be enabled for those diagnostics. @@ -1525,8 +1525,8 @@ end --- <pre> --- local s = "WARNING filename:27:3: Variable 'foo' does not exist" --- local pattern = "^(%w+) %w+:(%d+):(%d+): (.+)$" ---- local groups = {"severity", "lnum", "col", "message"} ---- vim.diagnostic.match(s, pattern, groups, {WARNING = vim.diagnostic.WARN}) +--- local groups = { "severity", "lnum", "col", "message" } +--- vim.diagnostic.match(s, pattern, groups, { WARNING = vim.diagnostic.WARN }) --- </pre> --- ---@param str string String to parse diagnostics from. diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 70c8cd15eb..1b209e6a9d 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -176,6 +176,7 @@ local extension = { bbappend = 'bitbake', bbclass = 'bitbake', bl = 'blank', + bsd = 'bsdl', bsdl = 'bsdl', bst = 'bst', btm = function(path, bufnr) @@ -968,7 +969,7 @@ local extension = { txi = 'texinfo', texinfo = 'texinfo', text = 'text', - tfvars = 'terraform', + tfvars = 'terraform-vars', tla = 'tla', tli = 'tli', toml = 'toml', @@ -1383,10 +1384,6 @@ local filename = { ['/etc/host.conf'] = 'hostconf', ['/etc/hosts.allow'] = 'hostsaccess', ['/etc/hosts.deny'] = 'hostsaccess', - ['/i3/config'] = 'i3config', - ['/sway/config'] = 'i3config', - ['/.sway/config'] = 'i3config', - ['/.i3/config'] = 'i3config', ['/.icewm/menu'] = 'icemenu', ['.indent.pro'] = 'indent', indentrc = 'indent', @@ -1668,7 +1665,6 @@ local pattern = { ['.*/build/conf/.*%.conf'] = 'bitbake', ['.*/meta/conf/.*%.conf'] = 'bitbake', ['.*/meta%-.*/conf/.*%.conf'] = 'bitbake', - ['.*bsd'] = 'bsdl', ['bzr_log%..*'] = 'bzr', ['.*enlightenment/.*%.cfg'] = 'c', ['cabal%.project%..*'] = starsetf('cabalproject'), @@ -1835,9 +1831,7 @@ local pattern = { ['.*/etc/hosts%.allow'] = 'hostsaccess', ['.*%.html%.m4'] = 'htmlm4', ['.*/%.i3/config'] = 'i3config', - ['.*/sway/config'] = 'i3config', ['.*/i3/config'] = 'i3config', - ['.*/%.sway/config'] = 'i3config', ['.*/%.icewm/menu'] = 'icemenu', ['.*/etc/initng/.*/.*%.i'] = 'initng', ['JAM.*%..*'] = starsetf('jam'), @@ -2076,6 +2070,8 @@ local pattern = { end, ['.*/etc/sudoers'] = 'sudoers', ['svn%-commit.*%.tmp'] = 'svn', + ['.*/sway/config'] = 'swayconfig', + ['.*/%.sway/config'] = 'swayconfig', ['.*%.swift%.gyb'] = 'swiftgyb', ['.*%.[Ss][Yy][Ss]'] = function(path, bufnr) return require('vim.filetype.detect').sys(bufnr) @@ -2241,30 +2237,30 @@ end --- <pre> --- vim.filetype.add({ --- extension = { ---- foo = "fooscript", +--- foo = 'fooscript', --- bar = function(path, bufnr) --- if some_condition() then ---- return "barscript", function(bufnr) +--- return 'barscript', function(bufnr) --- -- Set a buffer variable --- vim.b[bufnr].barscript_version = 2 --- end --- end ---- return "bar" +--- return 'bar' --- end, --- }, --- filename = { ---- [".foorc"] = "toml", ---- ["/etc/foo/config"] = "toml", +--- ['.foorc'] = 'toml', +--- ['/etc/foo/config'] = 'toml', --- }, --- pattern = { ---- [".*/etc/foo/.*"] = "fooscript", +--- ['.*/etc/foo/.*'] = 'fooscript', --- -- Using an optional priority ---- [".*/etc/foo/.*%.conf"] = { "dosini", { priority = 10 } }, ---- ["README.(%a+)$"] = function(path, bufnr, ext) ---- if ext == "md" then ---- return "markdown" ---- elseif ext == "rst" then ---- return "rst" +--- ['.*/etc/foo/.*%.conf'] = { 'dosini', { priority = 10 } }, +--- ['README.(%a+)$'] = function(path, bufnr, ext) +--- if ext == 'md' then +--- return 'markdown' +--- elseif ext == 'rst' then +--- return 'rst' --- end --- end, --- }, @@ -2279,9 +2275,9 @@ end --- priority = -math.huge, --- function(path, bufnr) --- local content = vim.filetype.getlines(bufnr, 1) ---- if vim.filetype.matchregex(content, { [[^#!.*\\<mine\\>]] }) then +--- if vim.filetype.matchregex(content, [[^#!.*\\<mine\\>]]) then --- return 'mine' ---- elseif vim.filetype.matchregex(content, { [[\\<drawing\\>]] }) then +--- elseif vim.filetype.matchregex(content, [[\\<drawing\\>]]) then --- return 'drawing' --- end --- end, diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua index 8c10517687..14f076717f 100644 --- a/runtime/lua/vim/filetype/detect.lua +++ b/runtime/lua/vim/filetype/detect.lua @@ -554,7 +554,7 @@ function M.inc(bufnr) -- headers so assume POV-Ray elseif findany(lines, { '^%s{', '^%s%(%*' }) or matchregex(lines, pascal_keywords) then return 'pascal' - elseif findany(lines, { '^%s*inherit ', '^%s*require ', '^%s*%w+%s+= ' }) then + elseif findany(lines, { '^%s*inherit ', '^%s*require ', '^%s*%u[%w_:${}]*%s+%??[?:+]?= ' }) then return 'bitbake' else local syntax = M.asm_syntax(bufnr) diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua index f4c2b507a9..7265beb56b 100644 --- a/runtime/lua/vim/keymap.lua +++ b/runtime/lua/vim/keymap.lua @@ -31,22 +31,19 @@ local keymap = {} --- vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end) --- </pre> --- ----@param mode string|table Same mode short names as |nvim_set_keymap()|. +---@param mode string|table Same mode short names as |nvim_set_keymap()|. --- Can also be list of modes to create mapping on multiple modes. ----@param lhs string Left-hand side |{lhs}| of the mapping. +---@param lhs string Left-hand side |{lhs}| of the mapping. ---@param rhs string|function Right-hand side |{rhs}| of the mapping. Can also be a Lua function. ---- If a Lua function and `opts.expr == true`, returning `nil` is ---- equivalent to an empty string. -- ---@param opts table A table of |:map-arguments| such as "silent". In addition to the options --- listed in |nvim_set_keymap()|, this table also accepts the following keys: --- - buffer: (number or boolean) Add a mapping to the given buffer. When "true" --- or 0, use the current buffer. ---- - replace_keycodes: (boolean, default true) When both this and expr is "true", ---- |nvim_replace_termcodes()| is applied to the result of Lua expr maps. --- - remap: (boolean) Make the mapping recursive. This is the --- inverse of the "noremap" option from |nvim_set_keymap()|. --- Default `false`. +--- - replace_keycodes: (boolean) defaults to true if "expr" is true. ---@see |nvim_set_keymap()| function keymap.set(mode, lhs, rhs, opts) vim.validate({ @@ -60,22 +57,9 @@ function keymap.set(mode, lhs, rhs, opts) local is_rhs_luaref = type(rhs) == 'function' mode = type(mode) == 'string' and { mode } or mode - if is_rhs_luaref and opts.expr then - local user_rhs = rhs - rhs = function() - local res = user_rhs() - if res == nil then - -- TODO(lewis6991): Handle this in C? - return '' - elseif opts.replace_keycodes ~= false then - return vim.api.nvim_replace_termcodes(res, true, true, true) - else - return res - end - end + if opts.expr and opts.replace_keycodes ~= false then + opts.replace_keycodes = true end - -- clear replace_keycodes from opts table - opts.replace_keycodes = nil if opts.remap == nil then -- default remap value is false diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 61586ca44f..bf2201d9c8 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -371,7 +371,9 @@ do state_by_client[client.id] = state end if not state.buffers[bufnr] then - local buf_state = {} + local buf_state = { + name = api.nvim_buf_get_name(bufnr), + } state.buffers[bufnr] = buf_state if use_incremental_sync then buf_state.lines = nvim_buf_get_lines(bufnr, 0, -1, true) @@ -382,6 +384,15 @@ do end ---@private + function changetracking._get_and_set_name(client, bufnr, name) + local state = state_by_client[client.id] 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_client[client.id] @@ -1405,6 +1416,19 @@ local function text_document_did_save_handler(bufnr) local uri = vim.uri_from_bufnr(bufnr) local text = once(buf_get_full_text) for_each_buffer_client(bufnr, function(client) + local name = api.nvim_buf_get_name(bufnr) + local old_name = changetracking._get_and_set_name(client, bufnr, name) + if old_name and name ~= old_name then + client.notify('textDocument/didOpen', { + textDocument = { + version = 0, + uri = uri, + languageId = client.config.get_language_id(bufnr, vim.bo[bufnr].filetype), + text = buf_get_full_text(bufnr), + }, + }) + util.buf_versions[bufnr] = 0 + end local save_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'save') if save_capability then local included_text diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 50a51e897c..63f4688d94 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -11,8 +11,8 @@ local M = {} --- buffer. --- ---@param method (string) LSP method name ----@param params (optional, table) Parameters to send to the server ----@param handler (optional, functionnil) See |lsp-handler|. Follows |lsp-handler-resolution| +---@param params (table|nil) Parameters to send to the server +---@param handler (function|nil) See |lsp-handler|. Follows |lsp-handler-resolution| -- ---@returns 2-tuple: --- - Map of client-id:request-id pairs for all successful requests. @@ -61,6 +61,7 @@ end --- ---@param options table|nil additional options --- - reuse_win: (boolean) Jump to existing window if buffer is already open. +--- - on_list: (function) handler for list results. See |on-list-handler| function M.declaration(options) local params = util.make_position_params() request_with_options('textDocument/declaration', params, options) @@ -70,6 +71,7 @@ end --- ---@param options table|nil additional options --- - reuse_win: (boolean) Jump to existing window if buffer is already open. +--- - on_list: (function) handler for list results. See |on-list-handler| function M.definition(options) local params = util.make_position_params() request_with_options('textDocument/definition', params, options) @@ -79,6 +81,7 @@ end --- ---@param options table|nil additional options --- - reuse_win: (boolean) Jump to existing window if buffer is already open. +--- - on_list: (function) handler for list results. See |on-list-handler| function M.type_definition(options) local params = util.make_position_params() request_with_options('textDocument/typeDefinition', params, options) @@ -86,9 +89,12 @@ end --- Lists all the implementations for the symbol under the cursor in the --- quickfix window. -function M.implementation() +--- +---@param options table|nil additional options +--- - on_list: (function) handler for list results. See |on-list-handler| +function M.implementation(options) local params = util.make_position_params() - request('textDocument/implementation', params) + request_with_options('textDocument/implementation', params, options) end --- Displays signature information about the symbol under the cursor in a @@ -151,7 +157,7 @@ end --- - formatting_options (table|nil): --- Can be used to specify FormattingOptions. Some unspecified options will be --- automatically derived from the current Neovim options. ---- @see https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting +--- See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#formattingOptions --- - timeout_ms (integer|nil, default 1000): --- Time in milliseconds to block for formatting requests. No effect if async=true --- - bufnr (number|nil): @@ -496,20 +502,24 @@ end --- ---@param context (table) Context for the request ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references -function M.references(context) +---@param options table|nil additional options +--- - on_list: (function) handler for list results. See |on-list-handler| +function M.references(context, options) validate({ context = { context, 't', true } }) local params = util.make_position_params() params.context = context or { includeDeclaration = true, } - request('textDocument/references', params) + request_with_options('textDocument/references', params, options) end --- Lists all symbols in the current buffer in the quickfix window. --- -function M.document_symbol() +---@param options table|nil additional options +--- - on_list: (function) handler for list results. See |on-list-handler| +function M.document_symbol(options) local params = { textDocument = util.make_text_document_params() } - request('textDocument/documentSymbol', params) + request_with_options('textDocument/documentSymbol', params, options) end ---@private @@ -648,13 +658,15 @@ end --- string means no filtering is done. --- ---@param query (string, optional) -function M.workspace_symbol(query) +---@param options table|nil additional options +--- - on_list: (function) handler for list results. See |on-list-handler| +function M.workspace_symbol(query, options) query = query or npcall(vim.fn.input, 'Query: ') if query == nil then return end local params = { query = query } - request('workspace/symbol', params) + request_with_options('workspace/symbol', params, options) end --- Send request to the server to resolve document highlights for the current @@ -830,20 +842,27 @@ end --- 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`. ---- - filter (function|nil): ---- Predicate function 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. +--- - 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`. +--- - 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| +--- ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction function M.code_action(options) validate({ options = { options, 't', true } }) @@ -858,7 +877,34 @@ function M.code_action(options) local bufnr = api.nvim_get_current_buf() context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics(bufnr) end - local params = util.make_range_params() + local params + local mode = api.nvim_get_mode().mode + if options.range then + assert(type(options.range) == 'table', 'code_action range must be a table') + local start = assert(options.range.start, 'range must have a `start` property') + local end_ = assert(options.range['end'], 'range must have a `end` property') + params = util.make_given_range_params(start, end_) + elseif mode == 'v' or mode == 'V' then + -- [bufnum, lnum, col, off]; both row and column 1-indexed + local start = vim.fn.getpos('v') + local end_ = vim.fn.getpos('.') + local start_row = start[2] + local start_col = start[3] + local end_row = end_[2] + local end_col = end_[3] + + -- A user can start visual selection at the end and move backwards + -- Normalize the range to start < end + if start_row == end_row and end_col < start_col then + end_col, start_col = start_col, end_col + elseif end_row < start_row then + start_row, end_row = end_row, start_row + start_col, end_col = end_col, start_col + end + params = util.make_given_range_params({ start_row, start_col - 1 }, { end_row, end_col - 1 }) + else + params = util.make_range_params() + end params.context = context code_action_request(params, options) end @@ -879,6 +925,7 @@ end ---@param end_pos ({number, number}, optional) mark-indexed position. ---Defaults to the end of the last visual selection. function M.range_code_action(context, start_pos, end_pos) + vim.deprecate('vim.lsp.buf.range_code_action', 'vim.lsp.buf.code_action', '0.9.0') validate({ context = { context, 't', true } }) context = context or {} if not context.diagnostics then diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 3b869d8f5c..1e6ac8dddf 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -189,19 +189,17 @@ M['textDocument/references'] = function(_, result, ctx, config) 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) + if config.loclist then - vim.fn.setloclist(0, {}, ' ', { - title = 'References', - items = util.locations_to_items(result, client.offset_encoding), - context = ctx, - }) + 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 = 'References', - items = util.locations_to_items(result, client.offset_encoding), - context = ctx, - }) + vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx }) api.nvim_command('botright copen') end end @@ -224,19 +222,17 @@ local function response_to_list(map_result, entity, title_fn) vim.notify('No ' .. entity .. ' found') 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_fn(ctx), - items = map_result(result, ctx.bufnr), - context = ctx, - }) + 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_fn(ctx), - items = map_result(result, ctx.bufnr), - context = ctx, - }) + vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx }) api.nvim_command('botright copen') end end @@ -261,6 +257,7 @@ end) --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename M['textDocument/rename'] = function(_, result, ctx, _) if not result then + 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) @@ -354,11 +351,16 @@ local function location_handler(_, result, ctx, config) util.jump_to_location(result[1], client.offset_encoding, config.reuse_win) if #result > 1 then - vim.fn.setqflist({}, ' ', { - title = 'LSP locations', - items = util.locations_to_items(result, client.offset_encoding), - }) - api.nvim_command('botright copen') + local title = 'LSP locations' + local items = util.locations_to_items(result, client.offset_encoding) + + if config.on_list then + assert(type(config.on_list) == 'function', 'on_list is not a function') + config.on_list({ title = title, items = items }) + else + vim.fn.setqflist({}, ' ', { title = title, items = items }) + api.nvim_command('botright copen') + end end else util.jump_to_location(result, client.offset_encoding, config.reuse_win) diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 6ecb9959d5..27da60b4ae 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -759,6 +759,7 @@ function protocol.make_client_capabilities() }, hierarchicalWorkspaceSymbolSupport = true, }, + configuration = true, workspaceFolders = true, applyEdit = true, workspaceEdit = { diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 70f5010256..8e89d92a56 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1821,7 +1821,7 @@ function M.try_trim_markdown_code_blocks(lines) end ---@private ----@param window (optional, number): window handle or 0 for current, defaults to current +---@param window number|nil: window handle or 0 for current, defaults to current ---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window` local function make_position_param(window, offset_encoding) window = window or 0 @@ -1841,7 +1841,7 @@ end --- Creates a `TextDocumentPositionParams` object for the current buffer and cursor position. --- ----@param window (optional, number): window handle or 0 for current, defaults to current +---@param window number|nil: window handle or 0 for current, defaults to current ---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window` ---@returns `TextDocumentPositionParams` object ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams @@ -1894,8 +1894,8 @@ end --- `textDocument/codeAction`, `textDocument/colorPresentation`, --- `textDocument/rangeFormatting`. --- ----@param window (optional, number): window handle or 0 for current, defaults to current ----@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window` +---@param window number|nil: window handle or 0 for current, defaults to current +---@param offset_encoding "utf-8"|"utf-16"|"utf-32"|nil defaults to `offset_encoding` of first client of buffer of `window` ---@returns { textDocument = { uri = `current_file_uri` }, range = { start = ---`current_position`, end = `current_position` } } function M.make_range_params(window, offset_encoding) @@ -1911,12 +1911,12 @@ end --- Using the given range in the current buffer, creates an object that --- is similar to |vim.lsp.util.make_range_params()|. --- ----@param start_pos ({number, number}, optional) mark-indexed position. ----Defaults to the start of the last visual selection. ----@param end_pos ({number, number}, optional) mark-indexed position. ----Defaults to the end of the last visual selection. ----@param bufnr (optional, number): buffer handle or 0 for current, defaults to current ----@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of `bufnr` +---@param start_pos number[]|nil {row, col} mark-indexed position. +--- Defaults to the start of the last visual selection. +---@param end_pos number[]|nil {row, col} mark-indexed position. +--- Defaults to the end of the last visual selection. +---@param bufnr number|nil buffer handle or 0 for current, defaults to current +---@param offset_encoding "utf-8"|"utf-16"|"utf-32"|nil defaults to `offset_encoding` of first client of `bufnr` ---@returns { textDocument = { uri = `current_file_uri` }, range = { start = ---`start_position`, end = `end_position` } } function M.make_given_range_params(start_pos, end_pos, bufnr, offset_encoding) @@ -1956,7 +1956,7 @@ end --- Creates a `TextDocumentIdentifier` object for the current buffer. --- ----@param bufnr (optional, number): Buffer handle, defaults to current +---@param bufnr number|nil: Buffer handle, defaults to current ---@returns `TextDocumentIdentifier` ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentIdentifier function M.make_text_document_params(bufnr) @@ -2000,7 +2000,7 @@ end --- Returns the UTF-32 and UTF-16 offsets for a position in a certain buffer. --- ----@param buf buffer id (0 for current) +---@param buf number buffer number (0 for current) ---@param row 0-indexed line ---@param col 0-indexed byte offset in line ---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of `buf` |