Configuration option: forget the current snippet when leaving the insert mode
I would like to be able to configure LuaSnip so it would abandon the current snippet when I'm leaving the insert mode.
The rationale.
After triggering the snippet, one may fill only some placeholders skipping others. Later I hit Tab (performs expand and/or jump in my setup) and LuaSnip sends me back to some placeholder I didn't before. I've tried to use the locally_jumpablefunction, but it solves the problem only partially.
I would like to configure LuaSnip in the same way as NeoSnippet works: when leaving the insert mode all placeholders must be forgotten.
P. S. I have tried to implement such behavior myself using autocommands on InsertLeave and InsertEnter, but because LuaSnip is switching modes during jumps such approach unlinks the snippet even when it shouldn't.
Does #258 work for you? I think it implements exactly the DIY-approach you mentioned, and handles mode-changes due to jumping around
It helps indeed! Thank you. I've had to tweak it a bit for my config, but it seems to be working as expected. I'll play with it for the next couple of days.
IMHO, it would be great to at least mention it in the documentation.
Nice👍
Adding it to the doc.. we don't have a section on jumping around, and tweaks for that so far, but it might be nice to add something like it.
We could also add this functionality in extras, that way it's easier to access, and we can confirm it continues to work, and isn't broken accidentally.
Just in case, here's a somewhat tweaked version using autocmd API & matching rather than code checks:
local luasnip = require('luasnip')
local unlinkgrp = vim.api.nvim_create_augroup(
'UnlinkSnippetOnModeChange',
{ clear = true }
)
vim.api.nvim_create_autocmd('ModeChanged', {
group = unlinkgrp,
pattern = {'s:n', 'i:*'},
desc = 'Forget the current snippet when leaving the insert mode',
callback = function(evt)
if
luasnip.session
and luasnip.session.current_nodes[evt.buf]
and not luasnip.session.jump_active
then
luasnip.unlink_current()
end
end,
})
An alternative version, courtesy of @bekaboo, which further takes into account the cursor-position can be found here
Regarding unlink_current, I have a question:
Would it be possible to relink the snippet, after it has been unlinked?
My use case is:
(1) Expand snippet
(2) Jump around in the snippet
(3a) Leave Insert Mode (running some command or do any other thing)
OR
(3b) manually trigger unlink_current and run some command, etc.
(4). Enter Insert Mode an resume jumping around in the snippet
Possibly, but I don't really see the point, the command will still modify the extmarks (if that's what you want to avoid) :/ Maybe just check the mode before performing a jump?
Just in case, here's a somewhat tweaked version using autocmd API & matching rather than code checks:
local luasnip = require('luasnip') local unlinkgrp = vim.api.nvim_create_augroup( 'UnlinkSnippetOnModeChange', { clear = true } ) vim.api.nvim_create_autocmd('ModeChanged', { group = unlinkgrp, pattern = {'s:n', 'i:*'}, desc = 'Forget the current snippet when leaving the insert mode', callback = function(evt) if luasnip.session and luasnip.session.current_nodes[evt.buf] and not luasnip.session.jump_active then luasnip.unlink_current() end end, })
This along with ext_opts was incredibly helpful in improving my luasnip experience. However I encountered a small flaw in this, in that it only unlinks the most recent snippet. So, for example if I use 2 snippets while in insert mode, only the most recent snippet will be unlinked. To get that behavior right I wrapped it in a loop:
vim.api.nvim_create_autocmd("ModeChanged", {
group = vim.api.nvim_create_augroup("UnlinkLuaSnipSnippetOnModeChange", {
clear = true,
}),
pattern = { "s:n", "i:*" },
desc = "Forget the current snippet when leaving the insert mode",
callback = function(evt)
-- If we have n active nodes, n - 1 will still remain after a `unlink_current()` call.
-- We unlink all of them by wrapping the calls in a loop.
while true do
if luasnip.session and luasnip.session.current_nodes[evt.buf] and not luasnip.session.jump_active then
luasnip.unlink_current()
else
break
end
end
end,
})
Does #258 work for you? I think it implements exactly the DIY-approach you mentioned, and handles mode-changes due to jumping around
Is there any way to update nodes before forgetting snippet?