mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 04:17:01 +00:00 
			
		
		
		
	feat(treesitter): add metadata option for get_node_text
This commit is contained in:
		| @@ -154,6 +154,9 @@ The following new APIs or features were added. | ||||
| • Treesitter captures can now be transformed by directives. This will allow | ||||
|   more complicated dynamic language injections. | ||||
|  | ||||
| • |vim.treesitter.query.get_node_text()| now accepts a `metadata` option for | ||||
|   writing custom directives using |vim.treesitter.query.add_directive()|. | ||||
|  | ||||
| ============================================================================== | ||||
| CHANGED FEATURES                                                 *news-changes* | ||||
|  | ||||
|   | ||||
| @@ -746,6 +746,9 @@ get_node_text({node}, {source}, {opts}) | ||||
|       • {opts}    (table|nil) Optional parameters. | ||||
|                   • concat: (boolean) Concatenate result in a string (default | ||||
|                     true) | ||||
|                   • metadata (table) Metadata of a specific capture. This | ||||
|                     would be set to `metadata[capture_id]` when using | ||||
|                     |vim.treesitter.query.add_directive()|. | ||||
|  | ||||
|     Return: ~ | ||||
|         (string[]|string|nil) | ||||
|   | ||||
| @@ -354,14 +354,6 @@ local function get_range_from_metadata(node, id, metadata) | ||||
|   return { node:range() } | ||||
| end | ||||
|  | ||||
| ---@private | ||||
| local function get_node_text(node, id, metadata, source) | ||||
|   if metadata[id] and metadata[id].text then | ||||
|     return metadata[id].text | ||||
|   end | ||||
|   return query.get_node_text(node, source) | ||||
| end | ||||
|  | ||||
| --- Gets language injection points by language. | ||||
| --- | ||||
| --- This is where most of the injection processing occurs. | ||||
| @@ -416,7 +408,7 @@ function LanguageTree:_get_injections() | ||||
|  | ||||
|         -- Lang should override any other language tag | ||||
|         if name == 'language' and not lang then | ||||
|           lang = get_node_text(node, id, metadata, self._source) --[[@as string]] | ||||
|           lang = query.get_node_text(node, self._source, { metadata = metadata[id] }) | ||||
|         elseif name == 'combined' then | ||||
|           combined = true | ||||
|         elseif name == 'content' and #ranges == 0 then | ||||
|   | ||||
| @@ -55,6 +55,38 @@ local function add_included_lang(base_langs, lang, ilang) | ||||
|   return false | ||||
| end | ||||
|  | ||||
| ---@private | ||||
| ---@param buf (number) | ||||
| ---@param range (table) | ||||
| ---@param concat (boolean) | ||||
| ---@returns (string[]|string|nil) | ||||
| local function buf_range_get_text(buf, range, concat) | ||||
|   local lines | ||||
|   local start_row, start_col, end_row, end_col = unpack(range) | ||||
|   local eof_row = a.nvim_buf_line_count(buf) | ||||
|   if start_row >= eof_row then | ||||
|     return nil | ||||
|   end | ||||
|  | ||||
|   if end_col == 0 then | ||||
|     lines = a.nvim_buf_get_lines(buf, start_row, end_row, true) | ||||
|     end_col = -1 | ||||
|   else | ||||
|     lines = a.nvim_buf_get_lines(buf, start_row, end_row + 1, true) | ||||
|   end | ||||
|  | ||||
|   if #lines > 0 then | ||||
|     if #lines == 1 then | ||||
|       lines[1] = string.sub(lines[1], start_col + 1, end_col) | ||||
|     else | ||||
|       lines[1] = string.sub(lines[1], start_col + 1) | ||||
|       lines[#lines] = string.sub(lines[#lines], 1, end_col) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   return concat and table.concat(lines, '\n') or lines | ||||
| end | ||||
|  | ||||
| --- Gets the list of files used to make up a query | ||||
| --- | ||||
| ---@param lang string Language to get query for | ||||
| @@ -240,40 +272,22 @@ end | ||||
| ---@param source (number|string) Buffer or string from which the {node} is extracted | ||||
| ---@param opts (table|nil) Optional parameters. | ||||
| ---          - concat: (boolean) Concatenate result in a string (default true) | ||||
| ---          - metadata (table) Metadata of a specific capture. This would be | ||||
| ---            set to `metadata[capture_id]` when using | ||||
| ---            |vim.treesitter.query.add_directive()|. | ||||
| ---@return (string[]|string|nil) | ||||
| function M.get_node_text(node, source, opts) | ||||
|   opts = opts or {} | ||||
|   local concat = vim.F.if_nil(opts.concat, true) | ||||
|   local metadata = opts.metadata or {} | ||||
|  | ||||
|   local start_row, start_col, start_byte = node:start() | ||||
|   local end_row, end_col, end_byte = node:end_() | ||||
|  | ||||
|   if type(source) == 'number' then | ||||
|     local eof_row = a.nvim_buf_line_count(source) | ||||
|     if start_row >= eof_row then | ||||
|       return nil | ||||
|     end | ||||
|  | ||||
|     local lines ---@type string[] | ||||
|     if end_col == 0 then | ||||
|       lines = a.nvim_buf_get_lines(source, start_row, end_row, true) | ||||
|       end_col = -1 | ||||
|     else | ||||
|       lines = a.nvim_buf_get_lines(source, start_row, end_row + 1, true) | ||||
|     end | ||||
|  | ||||
|     if #lines > 0 then | ||||
|       if #lines == 1 then | ||||
|         lines[1] = string.sub(lines[1], start_col + 1, end_col) | ||||
|       else | ||||
|         lines[1] = string.sub(lines[1], start_col + 1) | ||||
|         lines[#lines] = string.sub(lines[#lines], 1, end_col) | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     return concat and table.concat(lines, '\n') or lines | ||||
|   if metadata.text then | ||||
|     return metadata.text | ||||
|   elseif type(source) == 'number' then | ||||
|     return metadata.range and buf_range_get_text(source, metadata.range, concat) | ||||
|       or buf_range_get_text(source, { node:range() }, concat) | ||||
|   elseif type(source) == 'string' then | ||||
|     return source:sub(start_byte + 1, end_byte) | ||||
|     return source:sub(select(3, node:start()) + 1, select(3, node:end_())) | ||||
|   end | ||||
| end | ||||
|  | ||||
|   | ||||
| @@ -277,6 +277,9 @@ end]] | ||||
|       function fake_node:end_() | ||||
|         return 3, 0, 23 | ||||
|       end | ||||
|       function fake_node:range() | ||||
|         return 3, 0, 3, 0 | ||||
|       end | ||||
|       return vim.treesitter.get_node_text(fake_node, 0) == nil | ||||
|     ]]) | ||||
|     eq(true, result) | ||||
| @@ -296,6 +299,9 @@ end]] | ||||
|       function fake_node:end_() | ||||
|         return 1, 0, 7 | ||||
|       end | ||||
|       function fake_node:range() | ||||
|         return 1, 0, 1, 0 | ||||
|       end | ||||
|       return vim.treesitter.get_node_text(fake_node, 0) == '' | ||||
|     ]]) | ||||
|     eq(true, result) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 figsoda
					figsoda