aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/news.txt3
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua10
-rw-r--r--runtime/lua/vim/treesitter/query.lua15
-rw-r--r--test/functional/treesitter/parser_spec.lua2
4 files changed, 28 insertions, 2 deletions
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 5c234677ef..7c3f295560 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -151,6 +151,9 @@ The following new APIs or features were added.
• |:highlight| now supports an additional attribute "altfont".
+• Treesitter captures can now be transformed by directives. This will allow
+ more complicated dynamic language injections.
+
==============================================================================
CHANGED FEATURES *news-changes*
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 89aac3ae26..3e1bc5d1cb 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -354,6 +354,14 @@ 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.
@@ -408,7 +416,7 @@ function LanguageTree:_get_injections()
-- Lang should override any other language tag
if name == 'language' and not lang then
- lang = query.get_node_text(node, self._source) --[[@as string]]
+ lang = get_node_text(node, id, metadata, self._source) --[[@as string]]
elseif name == 'combined' then
combined = true
elseif name == 'content' and #ranges == 0 then
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 84ed2667b9..5ec8c67462 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -452,6 +452,21 @@ local directive_handlers = {
metadata[capture_id].range = range
end
end,
+
+ -- Transform the content of the node
+ -- Example: (#gsub! @_node ".*%.(.*)" "%1")
+ ['gsub!'] = function(match, _, bufnr, pred, metadata)
+ assert(#pred == 4)
+
+ local id = pred[2]
+ local node = match[id]
+ local text = M.get_node_text(node, bufnr, { metadata = metadata[id] }) or ''
+
+ if not metadata[id] then
+ metadata[id] = {}
+ end
+ metadata[id].text = text:gsub(pred[3], pred[4])
+ end,
}
--- Adds a new predicate to be used in queries
diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
index f006ad4539..0f187f3d52 100644
--- a/test/functional/treesitter/parser_spec.lua
+++ b/test/functional/treesitter/parser_spec.lua
@@ -728,7 +728,7 @@ int x = INT_MAX;
return list
]]
- eq({ 'offset!', 'set!' }, res_list)
+ eq({ 'gsub!', 'offset!', 'set!' }, res_list)
end)
end)
end)