LuaSnip
LuaSnip copied to clipboard
dynamic_node expands after undo
Hi, I'm not sure if this issue is an issue in LuaSnip or in my snippet.
The issue occurs when I expand my snippet func and then press u to undo.
I press ifunc<TAB><ESC>u (where <TAB> expands the snippet).
Expectation:
Either func or an empty line.
Behaviour:
M.name
If I then press u again I'm in the expected state with an empty line.
Sometimes when I've been deleting the input an error occurred on every input since LuaSnip was still in snippet mode even though the snippet was removed.
This is my config/snippet:
local luasnip = require 'luasnip'
luasnip.config.setup {
history = true,
store_selection_keys = '<TAB>',
updateevents = 'TextChanged,TextChangedI',
delete_check_events = 'TextChanged,InsertLeave',
}
local snip = luasnip.snippet
local node = luasnip.snippet_node
local text = luasnip.text_node
local insert = luasnip.insert_node
local func = luasnip.function_node
local choice = luasnip.choice_node
local dynamic = luasnip.dynamic_node
local function before(snippet)
return snippet.env.TM_CURRENT_LINE:match('^(.*)' .. snippet.dscr[1], 1)
end
luasnip.snippets = {
lua = {
snip('func', {
dynamic(1, function(_, snippet)
local line = before(snippet)
if line == '' then
return node(nil, choice(1, { text 'local ', text '' }))
elseif line:match '^%s*$' then
return node(nil, choice(1, { text '', text 'local ' }))
end
return node(nil, text '')
end, {}),
text 'function',
dynamic(2, function(args, snippet)
if not before(snippet):match '^%s*$' then
return node(nil, text '')
elseif args[1][1] ~= 'local ' then
return node(nil, { choice(1, { text ' M.', text ' ' }), insert(2, 'name') })
end
return node(nil, { text ' ', insert(1, 'name') })
end, { 1 }),
text '(',
insert(3, 'param'),
text { ')', '\t' },
dynamic(4, function(_, snippet)
local vis = snippet.env.TM_SELECTED_TEXT[1]
if vis then
return node(nil, { text(vis), insert(1) })
else
return insert(1, placeholder or '')
end
end, {}),
text { '', 'end' },
}),
},
}
Deleting snippets is a bit wonky :/
Setting delete_check_events = 'TextChanged,InsertLeave' is a good start, but sometimes the extmarks don't end up in the same place, which luasnip doesn't recognize as the snippet being deleted (I'll try adding some stuff to catch that, maybe that will end these problems).
One way of preventing them is doing :LuasnipUnlinkCurrent before deleting the snippet, but that's not a great experience.
Sometimes when I've been deleting the input an error occurred on every input since LuaSnip was still in snippet mode even though the snippet was removed.
Could you post the errors the next time they occur? We could put the source of the error into a pcall and delete the snippet upon catching one of those.
Thanks for the hint.
For now nnoremap u <CMD>LuaSnipUnlinkCurrent<CR>u works 👍
Hah, I found another bug: in config.lua, the autocommand for updating is defined (and therefore, for TextChanged, triggered) before the one for deleting the snippet if it has no text left.
Can you confirm that 21bdf39 and bdff107 fix your issue?
That looks like it fixed it 👍
Unfortunately it didn't fix the issue. In most cases it worked but I had an issue again where M.name kept coming.
ifunc<TAB><ESC>u is now working.
ifunc<ESC>i<TAB><ESC>u produces func M.name where the snippet isn't unlinked.
Same goes for ifunc<TAB><ESC><C-g>u basically when the trigger isn't removed by the undo.
I was also able to reproduce the mentioned error message:
Error detected while processing TextChanged Autocommands for "*":
E5108: Error executing lua ...k/packer/start/LuaSnip/lua/luasnip/nodes/dynamicNode.lua:186: attempt to index field 'snip' (a nil value)
stack traceback:
...k/packer/start/LuaSnip/lua/luasnip/nodes/dynamicNode.lua:186: in function 'exit'
.../pack/packer/start/LuaSnip/lua/luasnip/nodes/snippet.lua:767: in function 'exit'
.../pack/packer/start/LuaSnip/lua/luasnip/nodes/snippet.lua:237: in function 'remove_from_jumplist'
...nvim/site/pack/packer/start/LuaSnip/lua/luasnip/init.lua:294: in function 'unlink_current'
...nvim/site/pack/packer/start/LuaSnip/lua/luasnip/init.lua:317: in function 'active_update_dependents'
[string ":lua"]:1: in main chunk
The undo-problem arises again here because extmarks are not restored properly (at least it seems like that): directly after undoing, func is inside the mark-range, so we can't detect the snippet being deleted.
No idea how to catch that :/
As for the errors, more_delete_fixes should prevent them (but I'm not certain that this is the same error you were experiencing earlier, seems like this one was caused by bdff107).
Well for the most common use case ("insert, complete, undo since it's the wrong snippet") it's working. 👍
This should no longer occur with 6e951d8