Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix autosnippets #709

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion doc/luasnip.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*luasnip.txt* For NVIM v0.8.0 Last change: 2023 January 09
*luasnip.txt* For NVIM v0.8.0 Last change: 2023 January 14

==============================================================================
Table of Contents *luasnip-table-of-contents*
Expand Down
12 changes: 9 additions & 3 deletions lua/luasnip/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,16 @@ c = {
"Remove buffers' nodes on deletion+wipeout.
autocmd BufDelete,BufWipeout * lua current_nodes = require("luasnip").session.current_nodes if current_nodes then current_nodes[tonumber(vim.fn.expand("<abuf>"))] = nil end
]]
.. (session.config.enable_autosnippets and [[
.. (
session.config.enable_autosnippets
-- Luasnip_just_inserted makes sure we only trigger autosnippets after we inserted characters in insert mode.
-- vim.b.Luasnip_last_changedtick allows us to compute how many changes occurred in the file between two TextChanged* events. We use this information to distinguish typing characters by hand vs using <C-r> to paste multiple characters in insert mode. We want to allow expanding autosnippets in the first case and not in the second. After some investigation, this is the only way I found to distinguish the two cases.
Comment on lines +193 to +194
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% happy with this comment, I think it could be more descriptive, ie:

  1. what is the issue
  2. how can typing characters and pasting multiple characters be distinguished
  3. the solution

Also, could you make the comment 80-100 characters wide? Normally stylua should take care of this, but here it doesn't 🤷

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Actually, maybe stylua isn't supposed to..)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, and in a similar vein, could you shorten the comments in the tests?

and [[
autocmd InsertCharPre * lua Luasnip_just_inserted = true
autocmd TextChangedI,TextChangedP * lua if Luasnip_just_inserted then require("luasnip").expand_auto() Luasnip_just_inserted=nil end
]] or "")
autocmd TextChangedI,TextChangedP * lua if Luasnip_just_inserted then Luasnip_just_inserted=nil if vim.b.Luasnip_last_changedtick == nil or vim.b.changedtick==vim.b.Luasnip_last_changedtick + 1 then require("luasnip").expand_auto() end vim.b.Luasnip_last_changedtick = vim.b.changedtick end
Copy link
Owner

@L3MON4D3 L3MON4D3 Jan 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar here, could you spread this over multiple lines to increase readability?
Alternative would be to switch to lua-autocommands, but I don't think this alone warrants it.

]]
or ""
)
.. [[
augroup END
]],
Expand Down
30 changes: 29 additions & 1 deletion tests/integration/add_snippets_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@ local helpers = require("test.functional.helpers")(after_each)
local exec_lua, feed, exec = helpers.exec_lua, helpers.feed, helpers.exec
local ls_helpers = require("helpers")
local Screen = require("test.functional.ui.screen")
local sleep = require("luv").sleep

-- The integration tests here simulate typing into Neovim by feeding each simulated keystroke to Neovim one at a time.

-- Neovim's TextChangedI event responds to the simulated keystrokes differently from how we would expect it to when typing normally. Specifically, we expect the TextChangedI event to occur after every keystroke in insert mode when typing into Neovim normally, but in this simulation, TextChangedI only seems to occur after a pause.
-- For example, imagine we call feed("tri") and then feed("D"). We would normally expect four TextChangedI events, one after each letter ('t', 'r', 'i', and 'D'). However, according to my investigation, it only occurs after 'i' and 'D'. It only happens consistently if we include a sleep command after each call to feed.
local function feed_wait(...)
feed(...)
sleep(100)
end

describe("add_snippets", function()
local screen
Expand Down Expand Up @@ -282,7 +292,9 @@ describe("add_snippets", function()
})

feed("<ESC>cc") -- rewrite line
feed("triD")
-- We feed "tri" and "D" separately, because autosnippets need to have TextChangedI triggered on the character inserted before the trigger is complete or it will think that the trigger was pasted in (and therefore should not be auto-expanded) as it will appear that many characters were inserted all together.
feed_wait("tri")
feed_wait("D")
-- check if snippet "d" is automatically triggered
screen:expect({
grid = [[
Expand All @@ -291,6 +303,22 @@ describe("add_snippets", function()
{2:-- INSERT --} |]],
})

-- Test to make sure that autosnippets do not get triggered while pasting in insert mode.
feed("<ESC>dd") -- clear line
helpers.feed_command("set paste") -- disable autosnippets
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, why does set paste disable autosnippets? Had a cursory read of the help-section on it, but nothing in there caught my eye

helpers.insert("triD")
feed("<ESC>")
helpers.feed_command("set nopaste") -- reenable autosnippets
feed("<ESC>0d$") -- clear line
feed_wait([[i<C-r>"]]) -- use feed_wait here to wait for any auto expanding to occur (which it shouldn't)
-- make sure snippet is not automatically triggered. Ideally, autosnippets should never get triggered when we are pasting text. In most common cases, Luasnip should correctly avoid doing so.
screen:expect({
grid = [[
triD^ |
{0:~ }|
{2:-- INSERT --} |]],
})

feed("<ESC>cc") -- rewrite line
feed("triE")
-- check if snippet "e" is NOT automatically triggered
Expand Down