-
Notifications
You must be signed in to change notification settings - Fork 293
Description
Contributing guidelines
- I have read CONTRIBUTING.md
- I have read CODE_OF_CONDUCT.md
- I have updated 'mini.nvim' to latest version of the
mainbranch
Module(s)
mini.jump
Neovim version
0.12 (!at least latest Nightly build!)
Description
There is a window-of-opportunity in MiniJump.jump
local config = H.get_config()
H.timers.highlight:stop()
H.timers.highlight:start(
-- Update highlighting immediately if any highlighting is already present
H.is_highlighting() and 0 or config.delay.highlight,
0,
vim.schedule_wrap(function() H.highlight(hl_pattern) end)
)
Preconditions:
-
As a side-effect of the jump, a function is scheduled that will trigger a
BufLeaveevent -
After the jump, a function is scheduled immediately that will run
H.highlight(0 delay.highlight)
The problem:
On BufLeave, MiniJump.stop_jumping is called.
That will stop H.timers.highlight. However, the timer already scheduled the function.
Thus, H.highlight runs and applies the highlighting, although state.jumping is false.
This confuses the user, as the highlight indicates that the jump can be repeated by pressing f, F, t, T again.
I stumbled on this behavior when using mini.files
Reproduction
-
Create separate 'nvim-repro' config directory:
- '~/.config/nvim-repro/' on Unix
- '~/AppData/Local/nvim-repro/' on Windows
-
Inside 'nvim-repro' directory create a file named 'init.lua'.
Populate it with the following content:
vim.pack.add({ "https://github.com/nvim-mini/mini.nvim" })
require("mini.files").setup({
windows = { preview = true },
})
require("mini.jump").setup()
-
Run
NVIM_APPNAME=nvim-repro nvim(i.e. executenvimwithNVIM_APPNAMEenvironment variable set to "nvim-repro").
Wait for all dependencies to install. -
Replace this with description of interactive reproduction steps along with the behavior you observe.
Feel free to include images/videos/etc, this helps a lot.
jump_fix_bufleave.mp4
Three files, content is same as filename
- bar.txt
- rejump.txt
- star.txt
Happy flow
- Open Neovim, type
:MiniFiles.open()and enter - Notice that the cursor is on the first line and preview shows file 'bar.txt'
- Type
fu - Notice that the cursor is on the 'u' of 'rejump.txt'
- Notice that the preview now shows 'rejump.txt'
- Notice that there is no 'jump' highlighting
- Type
fand expectMiniJumpto prompt for a target
Annotated log using `MiniMisc.log_add`
{ --> MiniJump.jump "fu" jumping directly to next line, preview file 'rejump.txt'
desc = "Jump",
timestamp = 4845.994182
}, {
desc = "Jump end",
timestamp = 4846.599505
}, { --> MiniFiles receives CursorMoved and schedules its H.view_track_cursor
desc = "Scheduling H.view_track_cursor", w
state = {
buf = 2,
event = "CursorMoved",
file = "minifiles://2//home/user/.config/repro",
group = 9,
id = 30,
match = "minifiles://2//home/user/.config/repro"
},
timestamp = 4846.863891
}, { --> BufLeave event received from MiniFiles H.view_track_cursor
desc = "Event received to trigger stop_jumping",
state = {
buf = 3,
event = "BufLeave",
file = "minifiles://3//home/user/.config/repro/bar.txt",
group = 10,
id = 18,
match = "minifiles://3//home/user/.config/repro/bar.txt"
},
timestamp = 4853.303447
}, { --> BufLeave handlers immediately calls stop_jumping, stopping H.timers.highlight
desc = "Stop_jumping",
timestamp = 4853.307244
}, {
desc = "Stop_jumping end",
timestamp = 4853.314373
}}
--> End result: H.highlight is not invoked
Non happy flow
- Open Neovim, type
:MiniFiles.open()and enter - Notice that the cursor is on the first line and preview shows file 'bar.txt'
- Type
fr - Notice that the cursor is on the 'r' of 'bar.txt', still on the first line
- Notice that the preview still shows 'bar.txt'
- Notice that jump highlights all other 'r' in the
minifilesbuffer - Type
f - Notice that the cursor is now on the 'r' of 'rejump.txt'
- Notice that the preview now shows 'rejump.txt'
- Notice that jump still highlights all other 'r' in the
minifilesbuffer - Type
fand expect the cursor to move to the third line, 'star.txt' - However,
MiniJumpprompts for target
Annotated log using `MiniMisc.log_add`
{ --> MiniJump.jump "fr" jumping same line, still previews file 'bar.txt'
desc = "Jump",
timestamp = 10742.324058
}, {
desc = "Jump end",
timestamp = 10743.036937
}, { --> MiniFiles receives CursorMoved and schedules its H.view_track_cursor
--> The preview is for the same file, so there will not be a `BufLeave` event
desc = "Scheduling H.view_track_cursor",
state = {
buf = 2,
event = "CursorMoved",
file = "minifiles://2//home/user/.config/repro",
group = 9,
id = 30,
match = "minifiles://2//home/user/.config/repro"
},
timestamp = 10743.457255
}, { --> After 250ms delay, the timer schedules its call to H.highlight
desc = "Scheduling H.highlight",
state = "\\Vr",
timestamp = 10992.505875
}, { --> That schedule runs
desc = "H.highlight",
state = {
pattern = "\\Vr",
state = {
backward = false,
jumping = true,
mode = "n",
n_times = 1,
target = "r",
till = false
}
},
timestamp = 10992.580637
}, { --> Highlight applied
desc = "H.highlight end",
timestamp = 10992.866692
}, { --> MiniJump.jump "f" jumping to next line, preview file 'rejump.txt'
desc = "Jump",
timestamp = 14499.08062
}, {
desc = "Jump end",
timestamp = 14499.562205
}, { --> MiniFiles receives CursorMoved and schedules its H.view_track_cursor
desc = "Scheduling H.view_track_cursor",
state = {
buf = 2,
event = "CursorMoved",
file = "minifiles://2//home/user/.config/repro",
group = 9,
id = 30,
match = "minifiles://2//home/user/.config/repro"
},
timestamp = 14499.892646
}, { --> The timer schedules its call to H.highlight almost immediately after MiniJump.jump ends
desc = "Scheduling H.highlight",
state = "\\Vr",
timestamp = 14500.432876
}, { --> Scheduled MiniFiles H.view_track_cursor runs. MiniJump receives a BufLeave event
desc = "Event received to trigger stop_jumping",
state = {
buf = 3,
event = "BufLeave",
file = "minifiles://3//home/user/.config/repro/bar.txt",
group = 10,
id = 18,
match = "minifiles://3//home/user/.config/repro/bar.txt"
},
timestamp = 14506.417229
}, { --> BufLeave handler immediately calls stop_jumping, stopping H.timers.highlight
--> However, that timer has already **scheduled** the call to H.highlight! <--
desc = "Stop_jumping",
timestamp = 14506.42376
}, {
desc = "Stop_jumping end",
timestamp = 14506.440574
}, {
desc = "H.highlight",
state = {
pattern = "\\Vr",
state = {
backward = false,
jumping = false,
mode = "n",
n_times = 1,
target = "r",
till = false
}
},
timestamp = 14506.675274
}, { --> The scheduled call to H.highlight runs
--> The highlight is applied, even though state.jumping is now false! <--
desc = "H.highlight end",
timestamp = 14506.686243
}}Diff log statements
mini.files
diff --git a/lua/mini/files.lua b/lua/mini/files.lua
index 1776a65c..744a70fa 100644
--- a/lua/mini/files.lua
+++ b/lua/mini/files.lua
@@ -2135,7 +2135,10 @@ H.buffer_create = function(path, mappings)
vim.api.nvim_create_autocmd(events, { group = augroup, buffer = buf_id, desc = desc, callb
ack = callback })
end
- au({ 'CursorMoved', 'CursorMovedI', 'TextChangedP' }, 'Tweak cursor position', H.view_track_
cursor)
+ au({ 'CursorMoved', 'CursorMovedI', 'TextChangedP' }, 'Tweak cursor position', function(ev)
+ MiniMisc.log_add('Scheduling H.view_track_cursor', ev)
+ H.view_track_cursor(ev)
+ end)
au({ 'TextChanged', 'TextChangedI', 'TextChangedP' }, 'Track buffer modification', H.view_tr
ack_text_change)
-- Tweak buffer to be used nicely with other 'mini.nvim' modules
mini.jump
diff --git a/lua/mini/jump.lua b/lua/mini/jump.lua
index 0c802aa9..7df98094 100644
--- a/lua/mini/jump.lua
+++ b/lua/mini/jump.lua
@@ -179,6 +179,7 @@ MiniJump.state = {
---@param till __jump_till
---@param n_times __jump_n_times
MiniJump.jump = function(target, backward, till, n_times)
+ MiniMisc.log_add('Jump')
if H.is_disabled() then return end
-- Ensure to undo "consuming a character" effect if there is no target found
@@ -218,7 +219,10 @@ MiniJump.jump = function(target, backward, till, n_times)
-- Update highlighting immediately if any highlighting is already present
H.is_highlighting() and 0 or config.delay.highlight,
0,
- vim.schedule_wrap(function() H.highlight(hl_pattern) end)
+ function()
+ MiniMisc.log_add('Scheduling H.highlight', hl_pattern)
+ vim.schedule(function() H.highlight(hl_pattern) end)
+ end
)
-- Start idle timer after stopping previous one
@@ -249,6 +253,7 @@ MiniJump.jump = function(target, backward, till, n_times)
state_snapshot.jumping = true
MiniJump.state = state_snapshot
end
+ MiniMisc.log_add('Jump end')
end
--- Make smart jump
@@ -289,6 +294,7 @@ end
--- Removes highlights (if any) and forces the next smart jump to prompt for
--- the target. Automatically called on appropriate Neovim |events|.
MiniJump.stop_jumping = function()
+ MiniMisc.log_add('Stop_jumping')
H.timers.highlight:stop()
H.timers.idle_stop:stop()
@@ -303,6 +309,7 @@ MiniJump.stop_jumping = function()
-- Trigger relevant event only if there was jumping
if was_jumping then H.trigger_event('MiniJumpStop') end
+ MiniMisc.log_add('Stop_jumping end')
end
-- Helper data ================================================================
@@ -385,7 +392,10 @@ H.create_autocommands = function()
end
au('CursorMoved', '*', H.on_cursormoved, 'On CursorMoved')
- au({ 'BufLeave', 'InsertEnter' }, '*', MiniJump.stop_jumping, 'Stop jumping')
+ au({ 'BufLeave', 'InsertEnter' }, '*', function(ev)
+ MiniMisc.log_add('Event received to trigger stop_jumping', ev)
+ MiniJump.stop_jumping()
+ end, 'Stop jumping')
au('ColorScheme', '*', H.create_default_hl, 'Ensure colors')
end
@@ -478,10 +488,9 @@ end
-- Highlighting ---------------------------------------------------------------
H.highlight = function(pattern)
+ MiniMisc.log_add('H.highlight', { pattern = pattern, state = MiniJump.state })
-- Don't do anything if already highlighting input pattern
if H.is_highlighting(pattern) then return end
-- Stop highlighting possible previous pattern. Needed to adjust highlighting
-- when inside jumping but a different kind one. Example: first jump with
@@ -494,6 +503,7 @@ H.highlight = function(pattern)
local match_id = vim.fn.matchadd('MiniJump', pattern)
H.window_matches[vim.api.nvim_get_current_win()] = { id = match_id, pattern = pattern }
+ MiniMisc.log_add('H.highlight end')
end
H.unhighlight = function()
What to do after reporting an issue
After reporting the issue, it is safe (and even recommended for cleaner possible future bug reports) to remove 'nvim-repro' config from the system:
- Delete config directory ('~/.config/nvim-repro' on Unix).
- Delete data directory ('~/.local/share/nvim-repro' on Unix).
- Delete state directory ('~/.local/state/nvim-repro' on Unix).