LuaSnip
LuaSnip copied to clipboard
Treesitter Postfix not working
Trying to make snippet for rust, but for some reason cannot match the call expression here is the snippet code
treesitter_postfix({
trig = ".testing",
matchTSNode = {
query = [[(call_expression) @prefix]],
query_lang = "rust",
},
}, { t("hello") }),
whenever i try to use the snippet for example on piece of code like this
conn.interact(|conn|{todo!()})
instean replacing the code with "hello" it append it instead
The entire match to the query should be replaced, so it seems like the query matches an empty string for some reason.. What does the ts-node-tree look like after the trigger is inserted (":TSPlaygroundToggle")?
you mean like this
field_expression [12, 8] - [12, 42]
value: call_expression [12, 8] - [12, 37]
function: field_expression [12, 8] - [12, 21]
value: identifier [12, 8] - [12, 12]
field: field_identifier [12, 13] - [12, 21]
arguments: arguments [12, 21] - [12, 37]
closure_expression [12, 22] - [12, 36]
parameters: closure_parameters [12, 22] - [12, 28]
identifier [12, 23] - [12, 27]
body: macro_invocation [12, 29] - [12, 36]
macro: identifier [12, 29] - [12, 33]
token_tree [12, 34] - [12, 36]
unit_expression [12, 34] - [12, 36]
field: field_identifier [12, 38] - [12, 42]
Yup :+1:
Just did a test on my side, and here it's working fine (ts_px_add just immediately adds the postfix-snippet, so should be the same as your code)
https://github.com/L3MON4D3/LuaSnip/assets/41961280/7427780e-e036-4f20-8e5c-700c408b7a9c
Not sure what things may be going wrong for you, if you can produce a MWE I can look into it some more
probably my config, i use lazyvim with custom tweaks, i think it break some stuff. i will try to look into it
same here
config
local treesitter_postfix = require("luasnip.extras.treesitter_postfix").treesitter_postfix
local postfix_builtin = require("luasnip.extras.treesitter_postfix").builtin
ls.add_snippets("javascript", {
treesitter_postfix({
trig = ".mv",
matchTSNode = postfix_builtin.tsnode_matcher.find_topmost_types({
"call_expression",
"identifier"
}),
}, f(function(_, parent)
print(parent.snippet.env.LS_TSMATCH)
-- local node_content = table.concat(parent.snippet.env.LS_TSMATCH, '\n')
-- local replaced_content = ("std::move(%s)"):format(node_content)
-- return vim.split(ret_str, "\n", { trimempty = false })
end))
})
sorry for late response.
does adding the snippet using loaders.from_lua affect the result? the snippet is actually part of my project based snippet
here is my snippets
local tsp = require("luasnip.extras.treesitter_postfix").treesitter_postfix
return {
s(
"otw-task-runner",
fmt(
[[
pub(crate) async fn {}<Service, DbService, MsgService>(
service: &TaskRunnerInner<Service, DbService, MsgService>,
payload: {},
) -> anyhow::Result<()>
where
Service: 'static + Send + Sync + TaskRunnerService,
DbService: 'static + Send + Sync + DatabaseService,
MsgService: 'static + Send + Sync + MessageService,
{{
{}
}}]],
{
i(1, "runner"),
i(2, "Payload"),
i(3, "todo!()"),
}
)
),
tsp({
trig = ".inner",
matchTSNode = {
query = [[
(struct_item) @prefix
]],
query_lang = "rust",
},
}, {
t("hlleo"),
}),
}, {}
and the .inner snippet also showing up even if Treesitter query doesn't match up
config
local treesitter_postfix = require("luasnip.extras.treesitter_postfix").treesitter_postfix local postfix_builtin = require("luasnip.extras.treesitter_postfix").builtin ls.add_snippets("javascript", { treesitter_postfix({ trig = ".mv", matchTSNode = postfix_builtin.tsnode_matcher.find_topmost_types({ "call_expression", "identifier" }), }, f(function(_, parent) print(parent.snippet.env.LS_TSMATCH) -- local node_content = table.concat(parent.snippet.env.LS_TSMATCH, '\n') -- local replaced_content = ("std::move(%s)"):format(node_content) -- return vim.split(ret_str, "\n", { trimempty = false }) end)) })
the LS_TSMATCH return nil for some reason
config
local treesitter_postfix = require("luasnip.extras.treesitter_postfix").treesitter_postfix local postfix_builtin = require("luasnip.extras.treesitter_postfix").builtin ls.add_snippets("javascript", { treesitter_postfix({ trig = ".mv", matchTSNode = postfix_builtin.tsnode_matcher.find_topmost_types({ "call_expression", "identifier" }), }, f(function(_, parent) print(parent.snippet.env.LS_TSMATCH) -- local node_content = table.concat(parent.snippet.env.LS_TSMATCH, '\n') -- local replaced_content = ("std::move(%s)"):format(node_content) -- return vim.split(ret_str, "\n", { trimempty = false }) end)) })2023.11.18.01.10.09.webm
The config works for me.
https://github.com/L3MON4D3/LuaSnip/assets/6359934/0a572f2d-96d4-4db2-a923-8ce0578803d7
Maybe something wrong in your ts parser?
config
local treesitter_postfix = require("luasnip.extras.treesitter_postfix").treesitter_postfix local postfix_builtin = require("luasnip.extras.treesitter_postfix").builtin ls.add_snippets("javascript", { treesitter_postfix({ trig = ".mv", matchTSNode = postfix_builtin.tsnode_matcher.find_topmost_types({ "call_expression", "identifier" }), }, f(function(_, parent) print(parent.snippet.env.LS_TSMATCH) -- local node_content = table.concat(parent.snippet.env.LS_TSMATCH, '\n') -- local replaced_content = ("std::move(%s)"):format(node_content) -- return vim.split(ret_str, "\n", { trimempty = false }) end)) })2023.11.18.01.10.09.webm
The config works for me.
CleanShot.2023-11-29.at.16.43.17.mp4 Maybe something wrong in your ts parser?
What is your version of neovim?
config
local treesitter_postfix = require("luasnip.extras.treesitter_postfix").treesitter_postfix local postfix_builtin = require("luasnip.extras.treesitter_postfix").builtin ls.add_snippets("javascript", { treesitter_postfix({ trig = ".mv", matchTSNode = postfix_builtin.tsnode_matcher.find_topmost_types({ "call_expression", "identifier" }), }, f(function(_, parent) print(parent.snippet.env.LS_TSMATCH) -- local node_content = table.concat(parent.snippet.env.LS_TSMATCH, '\n') -- local replaced_content = ("std::move(%s)"):format(node_content) -- return vim.split(ret_str, "\n", { trimempty = false }) end)) })2023.11.18.01.10.09.webm
The config works for me. CleanShot.2023-11-29.at.16.43.17.mp4 Maybe something wrong in your ts parser?
What is your version of
neovim?
master
same issue, parent.snippet.env.LS_TSMATCH is nil
I'm stuck here and can't move.
and cpu 100% here
I took a look at this a little bit and found it fails for me in https://github.com/L3MON4D3/LuaSnip/blob/f3b3d3446bcbfa62d638b1903ff00a78b2b730a1/lua/luasnip/extras/treesitter_postfix.lua#L244 at check_node_exclude_pos
The values at this point are
end_row:96 == pos[1]:96
end_col:7 == pos[2]:4
Removing the check_node_exclude_pos makes parent.snippet.env.LS_TSMATCH contain data. But it contains the match with the postfix trigger. eg test/xx with /xx being the trigger. I assume the check at check_node_exclude_pos fails because the trigger was not correctly removed? Hence the 4 vs 7 comparison?
Also I get two callback to my function node. One with parent.snippet.env.LS_TSMATCH="$LS_TSMATCH" and the other with parent.snippet.env.LS_TSMATCH={ "test/xx" }. Not sure if this is normal.
this fixed it for me https://github.com/hfn92/LuaSnip/commit/9d1bf4a4fd7cd6c4d15d415d8e5b7a764e85d402
but not sure how much sense this makes ...
and I still get the $LS_TSMATCH from the fake_expand on the first expand.
I'm stuck here and can't move.
and cpu 100% here
can you try this #1145 see if the problem is solved
@TwIStOy seem solved, but treesitter still unavailable
I'm not sure if it's my own problem
i can't reproduce this on my machine. it seems like there's no captures can be found in the match. maybe you can use function node to show which captures are found
@yifan0414 have tried my branch (https://github.com/hfn92/LuaSnip/tree/fix)? maybe it fixes it for you as well
@hfn92 yes, it fixes my problem!. But I have a question, why even if the capture conditions are not met, the snippet will still be displayed. If you try to complete with Enter, an error will be shown. However, if the capture conditions are met, it will work correctly.
@yifan0414 I don't know exactly what happens, I was just playing around to see if I can fix this issue for me :sweat_smile: I don't know exactly whats going on but in first callback when resolving, 'LS_TSMATCH' is nil. I have a check in my callback to verify that LS_TSMATCH is not nil. This solves this error for me.
@yifan0414 Can you try to add reparseBuffer = "live" to your postfix snippet? This will remove trig first, then reparse the buffer, then try to expand the snippet.
And what's your neovim and nvim-treesitter version?
@hfn92 The LS_TSMATCH must not contains the trig. So only these nodes before current cursor are considered. Remove exclude current cursor check seems not a good idea. That may cause LS_TSMATCH is nil in callbacks.
@TwIStOy The nil LS_TSMATCH was being triggered from some fake_expand function, it only happens once.
I'm not claiming I know whats going here, but check_node_exclude_pos always failed for me because it compared length of node + trigger with length of node \w0 trigger. Removing the trigger fixed this for me
@TwIStOy reparseBuffer = "live" fixes it for me. Thanks!
@TwIStOy The nil LS_TSMATCH was being triggered from some fake_expand function, it only happens once.
Oh hey, fake_expand is used for generating docstrings for nvim-cmp, if you want to handle that gracefully, make sure to add a codepath that detects this (ie. LS_TSMATCH == nil) and returns some sane values (we can't provide them when generating docstrings, unfortunately)
@TwIStOy The nil LS_TSMATCH was being triggered from some fake_expand function, it only happens once.
Oh hey,
fake_expandis used for generating docstrings for nvim-cmp, if you want to handle that gracefully, make sure to add a codepath that detects this (ie.LS_TSMATCH == nil) and returns some sane values (we can't provide them when generating docstrings, unfortunately)
Ah I see, thank you!
and cpu 100% here 