diff options
Diffstat (limited to 'runtime/lua')
-rw-r--r-- | runtime/lua/vim/_defaults.lua | 1 | ||||
-rw-r--r-- | runtime/lua/vim/_inspector.lua | 7 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/api.lua | 6 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/json.lua | 5 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/options.lua | 34 | ||||
-rw-r--r-- | runtime/lua/vim/lsp.lua | 84 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/_folding_range.lua | 4 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/client.lua | 21 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 5 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/query.lua | 53 |
10 files changed, 123 insertions, 97 deletions
diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index f891c3baa4..0b8a54e957 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -495,6 +495,7 @@ do vim.wo[0][0].number = false vim.wo[0][0].relativenumber = false vim.wo[0][0].signcolumn = 'no' + vim.wo[0][0].foldcolumn = '0' -- This is gross. Proper list options support when? local winhl = vim.o.winhighlight diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua index f4e41a31e5..520c437906 100644 --- a/runtime/lua/vim/_inspector.lua +++ b/runtime/lua/vim/_inspector.lua @@ -191,7 +191,12 @@ function vim.show_pos(bufnr, row, col, filter) append('Treesitter', 'Title') nl() for _, capture in ipairs(items.treesitter) do - item(capture, capture.lang) + item( + capture, + capture.metadata.priority + and string.format('%s priority: %d', capture.lang, capture.metadata.priority) + or capture.lang + ) end nl() end diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index d74ee11b46..b2385197bd 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -963,9 +963,9 @@ function vim.api.nvim_create_augroup(name, opts) end --- - 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 [<amatch>] ---- - buf: (number) expanded value of [<abuf>] ---- - file: (string) expanded value of [<afile>] +--- - file: (string) [<afile>] (not expanded to a full path) +--- - match: (string) [<amatch>] (expanded to a full path) +--- - buf: (number) [<abuf>] --- - data: (any) arbitrary data passed from [nvim_exec_autocmds()] [event-data]() --- - command (string) optional: Vim command to execute on event. Cannot be used with --- {callback} diff --git a/runtime/lua/vim/_meta/json.lua b/runtime/lua/vim/_meta/json.lua index 07d89aafc8..1a7e87db9c 100644 --- a/runtime/lua/vim/_meta/json.lua +++ b/runtime/lua/vim/_meta/json.lua @@ -35,5 +35,8 @@ function vim.json.decode(str, opts) end --- Encodes (or "packs") Lua object {obj} as JSON in a Lua string. ---@param obj any +---@param opts? table<string,any> Options table with keys: +--- - escape_slash: (boolean) (default false) When true, escapes `/` +--- character in JSON strings ---@return string -function vim.json.encode(obj) end +function vim.json.encode(obj, opts) end diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 01d5235d94..59d270e640 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -3016,7 +3016,7 @@ vim.go.hid = vim.go.hidden --- A history of ":" commands, and a history of previous search patterns --- is remembered. This option decides how many entries may be stored in ---- each of these histories (see `cmdline-editing` and 'msghistory' for +--- each of these histories (see `cmdline-editing` and 'messagesopt' for --- the number of messages to remember). --- The maximum value is 10000. --- @@ -4084,6 +4084,28 @@ vim.o.mis = vim.o.menuitems vim.go.menuitems = vim.o.menuitems vim.go.mis = vim.go.menuitems +--- Option settings when outputting messages. It can consist of the +--- following items. Items must be separated by a comma. +--- +--- hit-enter Use `hit-enter` prompt when the message is longer than +--- 'cmdheight' size. +--- +--- wait:{n} Ignored when "hit-enter" is present. Instead of using +--- `hit-enter` prompt, will simply wait for {n} +--- milliseconds so the user has a chance to read the +--- message, use 0 to disable sleep (but then the user may +--- miss an important message). +--- +--- history:{n} Determines how many entries are remembered in the +--- `:messages` history. The maximum value is 10000. +--- Setting it to zero clears the message history. +--- +--- @type string +vim.o.messagesopt = "hit-enter,history:500" +vim.o.mopt = vim.o.messagesopt +vim.go.messagesopt = vim.o.messagesopt +vim.go.mopt = vim.go.messagesopt + --- Parameters for `:mkspell`. This tunes when to start compressing the --- word tree. Compression can be slow when there are many words, but --- it's needed to avoid running out of memory. The amount of memory used @@ -4379,16 +4401,6 @@ vim.o.mouset = vim.o.mousetime vim.go.mousetime = vim.o.mousetime vim.go.mouset = vim.go.mousetime ---- Determines how many entries are remembered in the `:messages` history. ---- The maximum value is 10000. ---- Setting it to zero clears the message history. ---- ---- @type integer -vim.o.msghistory = 500 -vim.o.mhi = vim.o.msghistory -vim.go.msghistory = vim.o.msghistory -vim.go.mhi = vim.go.msghistory - --- This defines what bases Vim will consider for numbers when using the --- CTRL-A and CTRL-X commands for adding to and subtracting from a number --- respectively; see `CTRL-A` for more info on these commands. diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 4717d7995a..e1946816da 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -114,6 +114,22 @@ function lsp._unsupported_method(method) return msg end +---@private +---@param workspace_folders string|lsp.WorkspaceFolder[]? +---@return lsp.WorkspaceFolder[]? +function lsp._get_workspace_folders(workspace_folders) + if type(workspace_folders) == 'table' then + return workspace_folders + elseif type(workspace_folders) == 'string' then + return { + { + uri = vim.uri_from_fname(workspace_folders), + name = workspace_folders, + }, + } + end +end + local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'error' } local format_line_ending = { @@ -196,19 +212,24 @@ local function reuse_client_default(client, config) return false end - if config.root_dir then - local root = vim.uri_from_fname(config.root_dir) - for _, dir in ipairs(client.workspace_folders or {}) do - -- note: do not need to check client.root_dir since that should be client.workspace_folders[1] - if root == dir.uri then - return true + local config_folders = lsp._get_workspace_folders(config.workspace_folders or config.root_dir) + or {} + local config_folders_included = 0 + + if not next(config_folders) then + return false + end + + for _, config_folder in ipairs(config_folders) do + for _, client_folder in ipairs(client.workspace_folders) do + if config_folder.uri == client_folder.uri then + config_folders_included = config_folders_included + 1 + break end end end - -- TODO(lewis6991): also check config.workspace_folders - - return false + return config_folders_included == #config_folders end --- Reset defaults set by `set_defaults`. @@ -311,9 +332,10 @@ end --- @inlinedoc --- --- 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: vim.lsp.ClientConfig): boolean) +--- running clients. The default implementation re-uses a client if it has the +--- same name and if the given workspace folders (or root_dir) are all included +--- in the client's workspace folders. +--- @field reuse_client? fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean --- --- Buffer handle to attach to if starting or re-using a client (0 for current). --- @field bufnr? integer @@ -1257,44 +1279,6 @@ function lsp.with(handler, override_config) end end ---- Helper function to use when implementing a handler. ---- This will check that all of the keys in the user configuration ---- are valid keys and make sense to include for this handler. ---- ---- Will error on invalid keys (i.e. keys that do not exist in the options) ---- @param name string ---- @param options table<string,any> ---- @param user_config table<string,any> -function lsp._with_extend(name, options, user_config) - user_config = user_config or {} - - local resulting_config = {} --- @type table<string,any> - for k, v in pairs(user_config) do - if options[k] == nil then - error( - debug.traceback( - string.format( - 'Invalid option for `%s`: %s. Valid options are:\n%s', - name, - k, - vim.inspect(vim.tbl_keys(options)) - ) - ) - ) - end - - resulting_config[k] = v - end - - for k, v in pairs(options) do - if resulting_config[k] == nil then - resulting_config[k] = v - end - end - - return resulting_config -end - --- Registry for client side commands. --- This is an extension point for plugins to handle custom commands which are --- not part of the core language server protocol specification. diff --git a/runtime/lua/vim/lsp/_folding_range.lua b/runtime/lua/vim/lsp/_folding_range.lua index 6a445017a3..2f1767aaf5 100644 --- a/runtime/lua/vim/lsp/_folding_range.lua +++ b/runtime/lua/vim/lsp/_folding_range.lua @@ -271,7 +271,9 @@ local function setup(bufnr) buffer = bufnr, callback = function(args) local client = assert(vim.lsp.get_client_by_id(args.data.client_id)) - request(bufnr, client) + if client:supports_method(vim.lsp.protocol.Methods.textDocument_foldingRange, bufnr) then + request(bufnr, client) + end end, }) api.nvim_create_autocmd('LspNotify', { diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index a83d75bf75..7eb023da39 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -365,21 +365,6 @@ local function get_name(id, config) return tostring(id) end ---- @param workspace_folders string|lsp.WorkspaceFolder[]? ---- @return lsp.WorkspaceFolder[]? -local function get_workspace_folders(workspace_folders) - if type(workspace_folders) == 'table' then - return workspace_folders - elseif type(workspace_folders) == 'string' then - return { - { - uri = vim.uri_from_fname(workspace_folders), - name = workspace_folders, - }, - } - end -end - --- @generic T --- @param x elem_or_list<T>? --- @return T[] @@ -417,7 +402,7 @@ function Client.create(config) 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 or config.root_dir), + workspace_folders = lsp._get_workspace_folders(config.workspace_folders or config.root_dir), root_dir = config.root_dir, _before_init_cb = config.before_init, _on_init_cbs = ensure_list(config.on_init), @@ -1174,7 +1159,7 @@ function Client:_add_workspace_folder(dir) end end - local wf = assert(get_workspace_folders(dir)) + local wf = assert(lsp._get_workspace_folders(dir)) self:notify(ms.workspace_didChangeWorkspaceFolders, { event = { added = wf, removed = {} }, @@ -1189,7 +1174,7 @@ end --- Remove a directory to the workspace folders. --- @param dir string? function Client:_remove_workspace_folder(dir) - local wf = assert(get_workspace_folders(dir)) + local wf = assert(lsp._get_workspace_folders(dir)) self:notify(ms.workspace_didChangeWorkspaceFolders, { event = { added = {}, removed = wf }, diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index ced8aa5745..5bf436f2ca 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -2162,6 +2162,11 @@ function M._refresh(method, opts) local first = vim.fn.line('w0', window) local last = vim.fn.line('w$', window) for _, client in ipairs(clients) do + for rid, req in pairs(client.requests) do + if req.method == method and req.type == 'pending' and req.bufnr == bufnr then + client:cancel_request(rid) + end + end client:request(method, { textDocument = textDocument, range = make_line_range_params(bufnr, first - 1, last - 1, client.offset_encoding), diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 1677e8d364..dbe3d54c2f 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -572,13 +572,17 @@ local directive_handlers = { metadata[id].text = text:gsub(pattern, replacement) end, - -- Trim blank lines from end of the node - -- Example: (#trim! @fold) - -- TODO(clason): generalize to arbitrary whitespace removal + -- Trim whitespace from both sides of the node + -- Example: (#trim! @fold 1 1 1 1) ['trim!'] = function(match, _, bufnr, pred, metadata) local capture_id = pred[2] assert(type(capture_id) == 'number') + local trim_start_lines = pred[3] == '1' + local trim_start_cols = pred[4] == '1' + local trim_end_lines = pred[5] == '1' or not pred[3] -- default true for backwards compatibility + local trim_end_cols = pred[6] == '1' + local nodes = match[capture_id] if not nodes or #nodes == 0 then return @@ -588,20 +592,45 @@ local directive_handlers = { local start_row, start_col, end_row, end_col = node:range() - -- Don't trim if region ends in middle of a line - if end_col ~= 0 then - return + local node_text = vim.split(vim.treesitter.get_node_text(node, bufnr), '\n') + if end_col == 0 then + -- get_node_text() will ignore the last line if the node ends at column 0 + node_text[#node_text + 1] = '' end - while end_row >= start_row do - -- As we only care when end_col == 0, always inspect one line above end_row. - local end_line = api.nvim_buf_get_lines(bufnr, end_row - 1, end_row, true)[1] + local end_idx = #node_text + local start_idx = 1 - if end_line ~= '' then - break + if trim_end_lines then + while end_idx > 0 and node_text[end_idx]:find('^%s*$') do + end_idx = end_idx - 1 + end_row = end_row - 1 + -- set the end position to the last column of the next line, or 0 if we just trimmed the + -- last line + end_col = end_idx > 0 and #node_text[end_idx] or 0 end + end + if trim_end_cols then + if end_idx == 0 then + end_row = start_row + end_col = start_col + else + local whitespace_start = node_text[end_idx]:find('(%s*)$') + end_col = (whitespace_start - 1) + (end_idx == 1 and start_col or 0) + end + end - end_row = end_row - 1 + if trim_start_lines then + while start_idx <= end_idx and node_text[start_idx]:find('^%s*$') do + start_idx = start_idx + 1 + start_row = start_row + 1 + start_col = 0 + end + end + if trim_start_cols and node_text[start_idx] then + local _, whitespace_end = node_text[start_idx]:find('^(%s*)') + whitespace_end = whitespace_end or 0 + start_col = (start_idx == 1 and start_col or 0) + whitespace_end end -- If this produces an invalid range, we just skip it. |