---@module 'tsql.token_select' ---@class mod_token_select local M = {} ---@class mod_ts_query M.ts_query = {} ---@class TSQuery ---@field query string the passthru for treesitter language parser M.TSQuery = {} M.TSQuery.__index = M.TSQuery ---@type Ctor<{query: string}, TSQuery> function M.TSQuery.new(q) local self = q setmetatable(self, M.TSQuery) self.__index = M.TSQuery return self end ---@class FileLoc ---@field row_0 number 0-index row location ---@field col_0 number 0-index col location M.FileLoc = {} M.FileLoc.__index = M.FileLoc ---@type Ctor<{row_0: number, col_0: number}, FileLoc> function M.FileLoc.new(file_loc) assert(file_loc ~= nil) local self = file_loc setmetatable(self, M.FileLoc) self.__index = M.FileLoc return self end ---@class QNode ---@field start FileLoc ---@field end_ex_col FileLoc ---@field buf QBuf M.QNode = {} M.QNode.__index = M.QNode ---@type Ctor<{start: FileLoc, end_ex_col: FileLoc, buf: QBuf}, QNode> function M.QNode.new(qnode) assert(qnode ~= nil) local self = qnode setmetatable(self, M.QNode) self.__index = M.QNode return self end ---@param treesitter_query string the passthru for treesitter language ---parser ---@return TSQuery function M.ts_query.from_scm(treesitter_query) return M.TSQuery.new { query = treesitter_query } end ---@param files QBuf[] ---@return QNode[] function M.TSQuery:find_nodes(files) local result = {} for _, file in ipairs(files) do if file.lang == nil then goto continue end local sts, parser = pcall(vim.treesitter.get_parser, file.bufnr, file.filetype) if not sts then -- NOTE: no parser for language goto continue end local tree = parser:parse()[1] local root = tree:root() ---@type Query local sts, query = pcall(vim.treesitter.query.parse, file.lang, self.query) if not sts then error("Error parsing query \"" .. self.query .. "\" on lang " .. file.lang .. " for file " .. file.path) end for _, match, _ in query:iter_matches(root, file.bufnr, 0, -1) do for id, node in pairs(match) do local start_row, start_col, end_row, end_col = node:range(false) local start = M.FileLoc.new { row_0 = start_row, col_0 = start_col } -- CORRECTNESS: -- :lua local parser = vim.treesitter.get_parser(0, 'lua'); local tree = parser:parse()[1]; local query = vim.treesitter.parse_query('lua', '(identifier) @name'); for id, node in query:iter_captures(tree:root(), 0) do local name = query.captures[id]; if name == 'name' and vim.treesitter.get_node_text(node, 0) == 'TSQuery' then local sr, sc, er, ec = node:range(); print(string.format("TSQuery Start: (%d, %d), End: (%d, %d)", sr, sc, er, ec)); end; end local end_ex_col = M.FileLoc.new { row_0 = end_row, col_0 = end_col } local qnode = M.QNode.new { buf = file, start = start, end_ex_col = end_ex_col } table.insert(result, qnode) end end ::continue:: end return result end return M