refactor(jump): only do extra search for target if there was no jump#2303
refactor(jump): only do extra search for target if there was no jump#2303echasnovski merged 1 commit intonvim-mini:backlogfrom
Conversation
Details: Instead of always checking if target exists in text, only do so if there was no jump. Additional benefit: The code using the cursor to check if a jump occurred can be replaced by a more direct check
|
The solution applied to solve issue #688 in February 2024 had a side-effect regarding highlighting. Relevant part of diff: @@ -364,6 +365,10 @@ H.make_expr_jump = function(backward, till)
if target == nil then return '<Esc>' end
H.update_state(target, backward, till, vim.v.count1)
+ vim.schedule(function()
+ if H.cache.has_changed_cursor then return end
+ vim.cmd('undo' .. (vim.fn.has('nvim-0.8') == 1 and '!' or ''))
+ end)
return 'v<Cmd>lua MiniJump.jump()<CR>'
Whilst the scheduled Scenario with file containing a single word:
Using its previous commit '1d49300d50a2'
Using the fix, commit '4f69339'
To restore the original highlighting: diff --git a/lua/mini/jump.lua b/lua/mini/jump.lua
index 234510b9..7bf50dd6 100644
--- a/lua/mini/jump.lua
+++ b/lua/mini/jump.lua
@@ -239,7 +239,8 @@ MiniJump.jump = function(target, backward, till, n_times)
-- Ensure to undo "consuming a character" effect if there is no target found
-- Do it here to also act on dot-repeat
if has_jumped or not is_expr then return end
- vim.schedule(function() vim.cmd('undo!') end)
+ -- vim.schedule(function() vim.cmd('undo!') end)
+ vim.api.nvim_create_autocmd('ModeChanged', { once = true, callback = function() vim.cmd('un
do!') end })
end
--- Make smart jumpI think it also is more precise to use the |
|
Thanks for the PR! I'll take a closer look a bit later (probably next week), as I can not quickly see if the new approach is optimal. Should be, as tests pass and it is negative diff 💪
I don't really understand why |
Me neither. I do think that the 'undo!' is the culprit here. If the command is deferred instead of scheduled, the highlighting is removed when the defer activates. In addition to 'ModeChanged', 'CursorMoved' also works. I also tried with 'nvim_feedkeys' and the escape character and did not succeed. In flash.nvim I found a snippet that does work. The diff with that code applied: diff --git a/lua/mini/jump.lua b/lua/mini/jump.lua
index 234510b9..8fc8cb0e 100644
--- a/lua/mini/jump.lua
+++ b/lua/mini/jump.lua
@@ -239,7 +239,11 @@ MiniJump.jump = function(target, backward, till, n_times)
-- Ensure to undo "consuming a character" effect if there is no target found
-- Do it here to also act on dot-repeat
if has_jumped or not is_expr then return end
- vim.schedule(function() vim.cmd('undo!') end)
+
+ -- vim.schedule(function() vim.cmd('undo!') end)
+ local t = function(str) return vim.api.nvim_replace_termcodes(str, true, true, true) end
+ vim.api.nvim_feedkeys(t('<C-\\><C-n>'), 'nx', false)
+ vim.api.nvim_feedkeys(t('<esc>'), 'n', false)
end
--- Make smart _jump_The disadvantage of that code is that test "can be dot-repeated if did not jump at first" breaks. I think one can argue that dot-repeating an operation that did not occur lacks intuitiveness. It's not supported by builtin dot-repeat. Surprisingly, flash is able to dot-repeat when initially the jump was not possible. Flash is not using 'expr' mappings though... |
I would rather avoid using
Yeah, indeed built-in dot-repeat does not work that way. The current behavior still makes more sense to me as it allows a smoother repeated actions like: |
|
Thanks again for the PR! It should now be a part of
Regarding this issue, I am not able to reproduce the steps you describe (maybe anymore or maybe I wasn't able to in the first place, don't remember). With the latest change in how Operator-pending and dot-repeat works, the best approach would be to keep highlighting only in the direction that dot-repeat will repeat, but as far as I can tell there is no existing code for that while adding one would be not concise. I was thinking about not highlighting when jumping in Operator-pending mode (since it is relatively easy to implement now), but indeed highlighting places where dot-repeat would take the cursor sounds useful. So not yet sure what to do here. One thing I am certain: I'd rather have any highlighting mismatch than add |
|
Thanks! if is_expr and not has_jumped then vim.schedule(function() vim.cmd('undo!') end) end
I had this originally and thought you'd like the undo statement outside the if better. But indeed, this is more expressive. |
Usually - yeah, early return in this kind of situations is nice. But in this case it fits a single line (although pretty convoluted) and reads almost to the point of not needing the comment. Two lines here is more simple though, so the this decision can depend on time of day or day of the week :) |
jump_no_highlight.mp4
That's strange. See the video.
I agree
If the highlighting is a requirement, than perhaps the onetime CursorMoved event, as shown in the video, can be considered. I think it might be an appropriate workaround, as indeed the cursor is moved when a character is consumed. Shall I create a separate issue? |
No highlighting after the first
That is such a niche and undocumented behavior (
Maybe that's a good idea, yeah. At least to (concisely) describe all this behavior. Please make a feature request that is more in terms of "adjust highlighting after jumping in Operator-pending mode", because this is the core problem here. Which my guess would require a fundamental solution: either by not highlighting, or rethinking the whole way of doing expression mapping jumping (and the |
Details:
Instead of always checking if target exists in text, only do so if there was no jump.
Additional benefit: The code using the cursor to check if a jump occurred can be replaced by a more direct check