From f15d6094fc67c1d26d73812522293329946c8419 Mon Sep 17 00:00:00 2001 From: Wsevolod Date: Thu, 2 Jun 2022 10:49:57 +0300 Subject: [PATCH 1/2] fix(lua): stop pending highlight.on_yank timer, if any (#18824) When yanking another range while previous yank is still highlighted, the pending timer could clear the highlight almost immediately (especially when using larger `timeout`, i.e. 2000) --- runtime/lua/vim/highlight.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua index 4105ef0675..335836e813 100644 --- a/runtime/lua/vim/highlight.lua +++ b/runtime/lua/vim/highlight.lua @@ -63,7 +63,8 @@ function M.range(bufnr, ns, higroup, start, finish, opts) end end -local yank_ns = api.nvim_create_namespace("hlyank") +local yank_ns = api.nvim_create_namespace('hlyank') +local yank_timer --- Highlight the yanked region --- --- use from init.vim via @@ -113,6 +114,9 @@ function M.on_yank(opts) local bufnr = api.nvim_get_current_buf() api.nvim_buf_clear_namespace(bufnr, yank_ns, 0, -1) + if yank_timer then + yank_timer:close() + end local pos1 = vim.fn.getpos("'[") local pos2 = vim.fn.getpos("']") @@ -129,7 +133,8 @@ function M.on_yank(opts) { regtype = event.regtype, inclusive = event.inclusive, priority = M.priorities.user } ) - vim.defer_fn(function() + yank_timer = vim.defer_fn(function() + yank_timer = nil if api.nvim_buf_is_valid(bufnr) then api.nvim_buf_clear_namespace(bufnr, yank_ns, 0, -1) end From fe42dea674c4aee742fccedb2743fb412de55b50 Mon Sep 17 00:00:00 2001 From: notomo Date: Thu, 16 Jun 2022 11:39:55 +0900 Subject: [PATCH 2/2] fix(lua): highlight.on_yank can close timer in twice #18976 check whether timer is closing in vim.defer_fn before closing --- runtime/lua/vim/_editor.lua | 10 +++++++--- test/functional/lua/highlight_spec.lua | 15 ++++++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 8e372b806c..e35a94e0e8 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -373,9 +373,13 @@ end function vim.defer_fn(fn, timeout) vim.validate { fn = { fn, 'c', true}; } local timer = vim.loop.new_timer() - timer:start(timeout, 0, vim.schedule_wrap(function() - timer:stop() - timer:close() + timer:start( + timeout, + 0, + vim.schedule_wrap(function() + if not timer:is_closing() then + timer:close() + end fn() end)) diff --git a/test/functional/lua/highlight_spec.lua b/test/functional/lua/highlight_spec.lua index 50eecb5d09..60d0ed5017 100644 --- a/test/functional/lua/highlight_spec.lua +++ b/test/functional/lua/highlight_spec.lua @@ -6,20 +6,29 @@ local command = helpers.command local clear = helpers.clear describe('vim.highlight.on_yank', function() - before_each(function() clear() end) it('does not show errors even if buffer is wiped before timeout', function() command('new') - exec_lua[[ + exec_lua([[ vim.highlight.on_yank({timeout = 10, on_macro = true, event = {operator = "y", regtype = "v"}}) vim.cmd('bwipeout!') - ]] + ]]) helpers.sleep(10) helpers.feed('') -- avoid hang if error message exists eq('', eval('v:errmsg')) end) + it('does not close timer twice', function() + exec_lua([[ + vim.highlight.on_yank({timeout = 10, on_macro = true, event = {operator = "y"}}) + vim.loop.sleep(10) + vim.schedule(function() + vim.highlight.on_yank({timeout = 0, on_macro = true, event = {operator = "y"}}) + end) + ]]) + eq('', eval('v:errmsg')) + end) end)