mytsutils.lua (2308B)
1 local M = {} 2 3 local ts = vim.treesitter 4 local ts_utils = require 'nvim-treesitter.ts_utils' 5 6 --- Indexes a match by the the name of it's capture 7 ---@param query Query 8 ---@param match TSMatch 9 ---@param key string 10 ---@return TSNode? 11 function M.index_by_name(query, match, key) 12 for id, node in pairs(match) do 13 if query.captures[id] == key then 14 return node 15 end 16 end 17 end 18 19 --- Finds the smallest match of the given query, containing the given point, in the given buffer 20 ---@param line number Line number to consider 21 ---@param col number Column number to consider 22 ---@param query Query Query to use for matching 23 ---@param bufnr buffer Buffer to consider 24 ---@param cname string? Name of the capture indicating the root of the match (for size computation), defaults to "_root" 25 ---@return TSMatch? match The match containing the node indicated by cname 26 ---@return TSNode? node The node indicated by cname 27 function M.find_smallest_match(line, col, query, bufnr, cname) 28 ---@type TSNode? 29 local root = ts_utils.get_root_for_position(line, col) 30 if not root then return end 31 32 ---@type TSMatch 33 local smallest 34 35 ---@type TSNode 36 local smallnode 37 38 ---@type number 39 local smalllen 40 41 cname = cname or "_root" 42 43 for _, match, _ in query:iter_matches(root, bufnr, line, line + 1) do 44 local node = M.index_by_name(query, match, cname) 45 if node then 46 if vim.treesitter.node_contains(node, { line, col, line, col }) then 47 local thislen = ts_utils.node_length(node) 48 if not smallest or smalllen > thislen then 49 smallest = match 50 smalllen = thislen 51 smallnode = node 52 end 53 end 54 end 55 end 56 57 return smallest, smallnode 58 end 59 60 61 --- Selects the provided nodes in character visual mode 62 ---@param start TSNode Node to use the get the starting position 63 ---@param stop TSNode? Node to use to get the end position (defaults to start) 64 function M.select(start, stop) 65 stop = stop or start 66 67 local start_row, start_col = start:start() 68 local end_row, end_col = stop:end_() 69 70 -- Force being into visual mode 71 if vim.api.nvim_get_mode().mode ~= 'v' then 72 vim.cmd "normal! v" 73 end 74 75 vim.api.nvim_win_set_cursor(0, { start_row + 1, start_col }) 76 vim.cmd "normal! o" 77 vim.api.nvim_win_set_cursor(0, { end_row + 1, end_col - 1 }) 78 end 79 80 return M