diff options
| author | Stephan Seitz <stephan.seitz@fau.de> | 2020-10-18 16:07:36 +0200 |
|---|---|---|
| committer | Kiyan Yazdani <yazdani.kiyan@protonmail.com> | 2020-10-26 18:22:19 +0100 |
| commit | aa4c3e83e3d347bf37161b117c8c1e2d95031d2d (patch) | |
| tree | 4cf5e112f79d7f6a26016413d8e6e94626688bec | |
| parent | feat(install): add "maintained" option to only install maintained parsers (diff) | |
| download | nvim-treesitter-aa4c3e83e3d347bf37161b117c8c1e2d95031d2d.tar nvim-treesitter-aa4c3e83e3d347bf37161b117c8c1e2d95031d2d.tar.gz nvim-treesitter-aa4c3e83e3d347bf37161b117c8c1e2d95031d2d.tar.bz2 nvim-treesitter-aa4c3e83e3d347bf37161b117c8c1e2d95031d2d.tar.lz nvim-treesitter-aa4c3e83e3d347bf37161b117c8c1e2d95031d2d.tar.xz nvim-treesitter-aa4c3e83e3d347bf37161b117c8c1e2d95031d2d.tar.zst nvim-treesitter-aa4c3e83e3d347bf37161b117c8c1e2d95031d2d.zip | |
Add virtual range for creating node-like objects from multiple nodes
| -rw-r--r-- | lua/nvim-treesitter/query.lua | 5 | ||||
| -rw-r--r-- | lua/nvim-treesitter/query_predicates.lua | 1 | ||||
| -rw-r--r-- | lua/nvim-treesitter/tsrange.lua | 145 |
3 files changed, 151 insertions, 0 deletions
diff --git a/lua/nvim-treesitter/query.lua b/lua/nvim-treesitter/query.lua index 09fdbbdde..4cb5993b4 100644 --- a/lua/nvim-treesitter/query.lua +++ b/lua/nvim-treesitter/query.lua @@ -1,5 +1,6 @@ local api = vim.api local tsq = require'vim.treesitter.query' +local tsrange = require'nvim-treesitter.tsrange' local utils = require'nvim-treesitter.utils' local parsers = require'nvim-treesitter.parsers' local caching = require'nvim-treesitter.caching' @@ -98,6 +99,10 @@ function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row) if pred[1] == "set!" and type(pred[2]) == "string" then insert_to_path(prepared_match, split(pred[2]), pred[3]) end + if pred[1] == "make-range!" and type(pred[2]) == "string" and #pred == 4 then + insert_to_path(prepared_match, split(pred[2]..'.node'), + tsrange.TSRange.from_nodes(bufnr, match[pred[3]], match[pred[4]])) + end end end diff --git a/lua/nvim-treesitter/query_predicates.lua b/lua/nvim-treesitter/query_predicates.lua index 0bcb905ec..0c0728997 100644 --- a/lua/nvim-treesitter/query_predicates.lua +++ b/lua/nvim-treesitter/query_predicates.lua @@ -66,3 +66,4 @@ end) -- Just avoid some anoying warnings for this predicate query.add_predicate('set!', function() return true end) +query.add_predicate('make-range!', function() return true end) diff --git a/lua/nvim-treesitter/tsrange.lua b/lua/nvim-treesitter/tsrange.lua new file mode 100644 index 000000000..e6aa73f5d --- /dev/null +++ b/lua/nvim-treesitter/tsrange.lua @@ -0,0 +1,145 @@ +local M = {} +local TSRange = {} +TSRange.__index = TSRange + +local api = vim.api +local parsers = require'nvim-treesitter.parsers' + +local function get_byte_offset(buf, row, col) + return api.nvim_buf_get_offset(buf, row) + + vim.fn.byteidx(api.nvim_buf_get_lines(buf, row, row + 1, false), col) +end + +function TSRange.new(buf, start_row, start_col, end_row, end_col) + return setmetatable( + { + start_pos = {start_row, start_col, get_byte_offset(buf, start_row, start_col)}, + end_pos = {end_row, end_col, get_byte_offset(buf, end_row, end_col)}, + buf = buf, + [1] = start_row, + [2] = start_col, + [3] = end_row, + [4] = end_col, + }, + TSRange) +end + +function TSRange.from_nodes(buf, start_node, end_node) + TSRange.__index = TSRange + local start_pos = {start_node:start()} + local end_pos = {end_node:end_()} + return setmetatable( + { + start_pos = {start_pos[1], start_pos[2], start_pos[3]}, + end_pos = {end_pos[1], end_pos[2], end_pos[3]}, + buf = buf, + [1] = start_pos[1], + [2] = start_pos[2], + [3] = end_pos[1], + [4] = end_pos[2], + }, + TSRange) +end + +function TSRange.from_table(buf, range) + return setmetatable( + { + start_pos = {range[1], range[2], get_byte_offset(buf, range[1], range[2])}, + end_pos = {range[3], range[4], get_byte_offset(buf, range[3], range[4])}, + buf = buf, + [1] = range[1], + [2] = range[2], + [3] = range[3], + [4] = range[4], + }, + TSRange) +end + +function TSRange:parent(range) + local parser = parsers.get_parser(self.buf, parsers.get_buf_lang(range)) + local root = parser.tree:root() + return root:named_descendant_for_range(self.start_pos[1], self.start_pos[2], self.end_pos[1], self.end_pos[2]) +end + +function TSRange:field() +end + +function TSRange:child_count() + return #self:collect_children() +end + +function TSRange:named_child_count() + return #self:collect_children(function(c) return c:named() end) +end + +function TSRange:iter_children() + local raw_iterator = self:parent().iter_children() + return function() + while true do + local node = raw_iterator() + if not node then return end + local _, _, start_byte = node:start() + local _, _, end_byte = node:end_() + if start_byte >= self.start_pos[3] and end_byte <= self.end_pos[3] then + return node + end + end + end +end + +function TSRange:collect_children(filter_fun) + local children = {} + for _, c in self:iter_children() do + if not filter_fun or filter_fun(c) then + table.insert(children, c) + end + end + return children +end + +function TSRange:child(index) + return self:collect_children()[index + 1] +end + +function TSRange:named_child(index) + return self:collect_children(function(c) return c.named() end)[index + 1] +end + +function TSRange:start() + return unpack(self.start_pos) +end + +function TSRange:end_() + return unpack(self.end_pos) +end + +function TSRange:range() + return self.start_pos[1], self.start_pos[2], self.end_pos[1], self.end_pos[2] +end + +function TSRange:type() + return 'nvim-treesitter-range' +end + +function TSRange:symbol() + return -1 +end + +function TSRange:named() + return false +end + +function TSRange:missing() + return false +end + +function TSRange:has_error() + return #self:collect_children(function(c) return c:has_error() end) > 0 and true or false +end + +function TSRange:sexpr() + return table.concat(vim.tbl_map(function(c) return c:sexpr() end, self:collect_children()), ' ') +end + +M.TSRange = TSRange +return M |
