nvim-config

Log | Files | Refs | README

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