diff options
Diffstat (limited to 'runtime/lua/vim')
-rw-r--r-- | runtime/lua/vim/highlight.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/lsp.lua | 10 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/rpc.lua | 1 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 10 | ||||
-rw-r--r-- | runtime/lua/vim/shared.lua | 18 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter.lua | 39 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/highlighter.lua | 28 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/query.lua | 51 |
8 files changed, 93 insertions, 66 deletions
diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua index ce0a3de520..705b34dc99 100644 --- a/runtime/lua/vim/highlight.lua +++ b/runtime/lua/vim/highlight.lua @@ -14,7 +14,7 @@ function highlight.range(bufnr, ns, higroup, start, finish, rtype, inclusive) inclusive = inclusive or false -- sanity check - if start[2] < 0 or finish[2] < start[2] then return end + if start[2] < 0 or finish[1] < start[1] then return end local region = vim.region(bufnr, start, finish, rtype, inclusive) for linenr, cols in pairs(region) do diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 47dca40208..585528dd5a 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -761,8 +761,12 @@ do text_document_did_change_handler = function(_, bufnr, changedtick, firstline, lastline, new_lastline, old_byte_size, old_utf32_size, old_utf16_size) - local _ = log.debug() and log.debug("on_lines", bufnr, changedtick, firstline, - lastline, new_lastline, old_byte_size, old_utf32_size, old_utf16_size, nvim_buf_get_lines(bufnr, firstline, new_lastline, true)) + + local _ = log.debug() and log.debug( + string.format("on_lines bufnr: %s, changedtick: %s, firstline: %s, lastline: %s, new_lastline: %s, old_byte_size: %s, old_utf32_size: %s, old_utf16_size: %s", + bufnr, changedtick, firstline, lastline, new_lastline, old_byte_size, old_utf32_size, old_utf16_size), + nvim_buf_get_lines(bufnr, firstline, new_lastline, true) + ) -- Don't do anything if there are no clients attached. if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then @@ -922,7 +926,7 @@ end --- To stop all clients: --- --- <pre> ---- vim.lsp.stop_client(lsp.get_active_clients()) +--- vim.lsp.stop_client(vim.lsp.get_active_clients()) --- </pre> --- --- By default asks the server to shutdown, unless stop was requested diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 680e1ba6ae..64080cf4f2 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -376,7 +376,6 @@ local function start(cmd, cmd_args, handlers, extra_spawn_params) --@param params (table): Parameters for the invoked LSP method --@returns (bool) `true` if notification could be sent, `false` if not local function notify(method, params) - local _ = log.debug() and log.debug("rpc.notify", method, params) return encode_and_send { jsonrpc = "2.0"; method = method; diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 3ec7311d65..24cb454e5b 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -299,10 +299,9 @@ end --- --@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion local function sort_completion_items(items) - if items[1] and items[1].sortText then - table.sort(items, function(a, b) return a.sortText < b.sortText - end) - end + table.sort(items, function(a, b) + return (a.sortText or a.label) < (b.sortText or b.label) + end) end --@private @@ -1438,6 +1437,9 @@ local function make_position_param() local row, col = unpack(api.nvim_win_get_cursor(0)) row = row - 1 local line = api.nvim_buf_get_lines(0, row, row+1, true)[1] + if not line then + return { line = 0; character = 0; } + end col = str_utfindex(line, col) return { line = row; character = col; } end diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 6e427665f2..5c89c63f7b 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -190,10 +190,10 @@ function vim.tbl_contains(t, value) return false end --- Returns true if the table is empty, and contains no indexed or keyed values. --- ---@see From https://github.com/premake/premake-core/blob/master/src/base/table.lua --- +--- Checks if a table is empty. +--- +--@see https://github.com/premake/premake-core/blob/master/src/base/table.lua +--- --@param t Table to check function vim.tbl_isempty(t) assert(type(t) == 'table', string.format("Expected table, got %s", type(t))) @@ -347,13 +347,11 @@ function vim.tbl_flatten(t) return result end ---- Determine whether a Lua table can be treated as an array. +--- Tests if a Lua table can be treated as an array. --- ---- An empty table `{}` will default to being treated as an array. ---- Use `vim.emtpy_dict()` to create a table treated as an ---- empty dict. Empty tables returned by `rpcrequest()` and ---- `vim.fn` functions can be checked using this function ---- whether they represent empty API arrays and vimL lists. +--- Empty table `{}` is assumed to be an array, unless it was created by +--- |vim.empty_dict()| or returned as a dict-like |API| or Vimscript result, +--- for example from |rpcrequest()| or |vim.fn|. --- --@param t Table --@returns `true` if array-like table, else `false`. diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 550dee1e3f..3a475b8f98 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -33,16 +33,23 @@ function Parser:parse() return self.tree, changes end -function Parser:_on_lines(bufnr, changed_tick, start_row, old_stop_row, stop_row, old_byte_size) - local start_byte = a.nvim_buf_get_offset(bufnr,start_row) - local stop_byte = a.nvim_buf_get_offset(bufnr,stop_row) - local old_stop_byte = start_byte + old_byte_size - self._parser:edit(start_byte,old_stop_byte,stop_byte, - start_row,0,old_stop_row,0,stop_row,0) +function Parser:_on_bytes(bufnr, changed_tick, + start_row, start_col, start_byte, + old_row, old_col, old_byte, + new_row, new_col, new_byte) + local old_end_col = old_col + ((old_row == 0) and start_col or 0) + local new_end_col = new_col + ((new_row == 0) and start_col or 0) + self._parser:edit(start_byte,start_byte+old_byte,start_byte+new_byte, + start_row, start_col, + start_row+old_row, old_end_col, + start_row+new_row, new_end_col) self.valid = false - for _, cb in ipairs(self.lines_cbs) do - cb(bufnr, changed_tick, start_row, old_stop_row, stop_row, old_byte_size) + for _, cb in ipairs(self.bytes_cbs) do + cb(bufnr, changed_tick, + start_row, start_col, start_byte, + old_row, old_col, old_byte, + new_row, new_col, new_byte) end end @@ -88,12 +95,12 @@ function M._create_parser(bufnr, lang, id) local self = setmetatable({bufnr=bufnr, lang=lang, valid=false}, Parser) self._parser = vim._create_ts_parser(lang) self.changedtree_cbs = {} - self.lines_cbs = {} + self.bytes_cbs = {} self:parse() - -- TODO(bfredl): use weakref to self, so that the parser is free'd is no plugin is - -- using it. - local function lines_cb(_, ...) - return self:_on_lines(...) + -- TODO(bfredl): use weakref to self, so that the parser is free'd is no plugin is + -- using it. + local function bytes_cb(_, ...) + return self:_on_bytes(...) end local detach_cb = nil if id ~= nil then @@ -103,7 +110,7 @@ function M._create_parser(bufnr, lang, id) end end end - a.nvim_buf_attach(self.bufnr, false, {on_lines=lines_cb, on_detach=detach_cb}) + a.nvim_buf_attach(self.bufnr, false, {on_bytes=bytes_cb, on_detach=detach_cb}) return self end @@ -138,8 +145,8 @@ function M.get_parser(bufnr, lang, buf_attach_cbs) table.insert(parsers[id].changedtree_cbs, buf_attach_cbs.on_changedtree) end - if buf_attach_cbs and buf_attach_cbs.on_lines then - table.insert(parsers[id].lines_cbs, buf_attach_cbs.on_lines) + if buf_attach_cbs and buf_attach_cbs.on_bytes then + table.insert(parsers[id].bytes_cbs, buf_attach_cbs.on_bytes) end return parsers[id] diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 681d2c6324..718088e0ad 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -60,14 +60,11 @@ function TSHighlighter.new(query, bufnr, ft) ft, { on_changedtree = function(...) self:on_changedtree(...) end, - on_lines = function() self.root = self.parser:parse():root() end + on_bytes = function() self.parser:parse() end } ) self.buf = self.parser.bufnr - - local tree = self.parser:parse() - self.root = tree:root() self:set_query(query) self.edit_count = 0 self.redraw_count = 0 @@ -98,7 +95,8 @@ function TSHighlighter:get_hl_from_capture(capture) return vim.split(name, '.', true)[1] else -- Default to false to avoid recomputing - return TSHighlighter.hl_map[name] + local hl = TSHighlighter.hl_map[name] + return hl and a.nvim_get_hl_id_by_name(hl) or 0 end end @@ -125,27 +123,25 @@ function TSHighlighter:set_query(query) end }) - self:on_changedtree({{self.root:range()}}) + self:on_changedtree({{self.parser:parse():root():range()}}) end function TSHighlighter:on_changedtree(changes) -- Get a fresh root - self.root = self.parser.tree:root() + local root = self.parser:parse():root() for _, ch in ipairs(changes or {}) do - -- Try to be as exact as possible - local changed_node = self.root:descendant_for_range(ch[1], ch[2], ch[3], ch[4]) - - a.nvim_buf_clear_namespace(self.buf, ts_hs_ns, ch[1], ch[3]) + a.nvim_buf_clear_namespace(self.buf, ts_hs_ns, ch[1], ch[3]+1) - for capture, node in self.query:iter_captures(changed_node, self.buf, ch[1], ch[3] + 1) do + for capture, node in self.query:iter_captures(root, self.buf, ch[1], ch[3] + 1) do local start_row, start_col, end_row, end_col = node:range() local hl = self.hl_cache[capture] if hl then - a.nvim__buf_add_decoration(self.buf, ts_hs_ns, hl, - start_row, start_col, - end_row, end_col, - {}) + a.nvim_buf_set_extmark(self.buf, ts_hs_ns, start_row, start_col, { + end_col = end_col, + end_line = end_row, + hl_group = hl + }) end end end diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 17f61b24f1..ca27a50c6a 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -17,7 +17,7 @@ local M = {} function M.parse_query(lang, query) language.require_language(lang) local self = setmetatable({}, Query) - self.query = vim._ts_parse_query(lang, vim.fn.escape(query,'\\')) + self.query = vim._ts_parse_query(lang, query) self.info = self.query:inspect() self.captures = self.info.captures return self @@ -60,7 +60,7 @@ local predicate_handlers = { return true end, - ["match?"] = function(match, _, bufnr, predicate) + ["lua-match?"] = function(match, _, bufnr, predicate) local node = match[predicate[2]] local regex = predicate[3] local start_row, _, end_row, _ = node:range() @@ -71,7 +71,7 @@ local predicate_handlers = { return string.find(M.get_node_text(node, bufnr), regex) end, - ["vim-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 @@ -82,7 +82,7 @@ local predicate_handlers = { local compiled_vim_regexes = setmetatable({}, { __index = function(t, pattern) - local res = vim.regex(check_magic(pattern)) + local res = vim.regex(check_magic(vim.fn.escape(pattern, '\\'))) rawset(t, pattern, res) return res end @@ -114,6 +114,9 @@ local predicate_handlers = { end } +-- As we provide lua-match? also expose vim-match? +predicate_handlers["vim-match?"] = predicate_handlers["match?"] + --- Adds a new predicates to be used in queries -- -- @param name the name of the predicate, without leading # @@ -127,25 +130,43 @@ function M.add_predicate(name, handler, force) predicate_handlers[name] = handler end +--- Returns the list of currently supported predicates +function M.list_predicates() + return vim.tbl_keys(predicate_handlers) +end + +local function xor(x, y) + return (x or y) and not (x and y) +end + function Query:match_preds(match, pattern, bufnr) local preds = self.info.patterns[pattern] - if not preds then - return true - end - for _, pred in pairs(preds) do + + for _, pred in pairs(preds or {}) do -- Here we only want to return if a predicate DOES NOT match, and -- 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 + local is_not if string.sub(pred[1], 1, 4) == "not-" then - local pred_name = string.sub(pred[1], 5) - if predicate_handlers[pred_name] and - predicate_handlers[pred_name](match, pattern, bufnr, pred) then - return false - end + pred_name = string.sub(pred[1], 5) + is_not = true + else + pred_name = pred[1] + is_not = false + end + + local handler = predicate_handlers[pred_name] + + if not handler then + a.nvim_err_writeln(string.format("No handler for %s", pred[1])) + return false + end + + local pred_matches = handler(match, pattern, bufnr, pred) - elseif predicate_handlers[pred[1]] and - not predicate_handlers[pred[1]](match, pattern, bufnr, pred) then + if not xor(is_not, pred_matches) then return false end end |