Skip to content

Commit 1858dea

Browse files
abeldekatechasnovski
authored andcommitted
feat(jump)!: make dot-repeat jumping separate from regular jumping
Resolve #2054
1 parent e1e6f68 commit 1858dea

2 files changed

Lines changed: 70 additions & 3 deletions

File tree

lua/mini/jump.lua

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@ MiniJump.state = {
181181
MiniJump.jump = function(target, backward, till, n_times)
182182
if H.is_disabled() then return end
183183

184+
-- If dot-repeating the state needs to be restored after the jump
185+
local needs_restore = MiniJump._is_expr and MiniJump.state.mode ~= 'no'
186+
MiniJump._is_expr = nil
187+
local state_snapshot = needs_restore and vim.deepcopy(MiniJump.state) or nil
188+
184189
-- Cache inputs for future use
185190
H.update_state(target, backward, till, n_times)
186191

@@ -230,6 +235,12 @@ MiniJump.jump = function(target, backward, till, n_times)
230235
-- Track cursor position to account for movement not caught by `CursorMoved`
231236
H.cache.latest_cursor = H.get_cursor_data()
232237
H.cache.has_changed_cursor = not vim.deep_equal(H.cache.latest_cursor, init_cursor_data)
238+
239+
-- If dot-repeating restore the state to its value from before this jump
240+
if needs_restore then
241+
state_snapshot.jumping = true
242+
MiniJump.state = state_snapshot
243+
end
233244
end
234245

235246
--- Make smart jump
@@ -383,7 +394,8 @@ H.make_expr_jump = function(backward, till)
383394
return function()
384395
if H.is_disabled() then return '' end
385396

386-
H.update_state(nil, backward, till, vim.v.count1)
397+
local count = vim.v.count1
398+
H.update_state(nil, backward, till, count)
387399

388400
-- Ask for `target` for non-repeating jump as this will be used only in
389401
-- operator-pending mode. Dot-repeat is supported via expression-mapping.
@@ -398,7 +410,10 @@ H.make_expr_jump = function(backward, till)
398410
if H.cache.has_changed_cursor then return end
399411
vim.cmd('undo!')
400412
end)
401-
return 'v<Cmd>lua MiniJump.jump()<CR>'
413+
414+
-- Encode state in expression for dot-repeat
415+
local args = string.format('%s,%s,%s,%s', vim.inspect(target), backward, till, count)
416+
return 'v<Cmd>lua MiniJump._is_expr=true; MiniJump.jump(' .. args .. ')<CR>'
402417
end
403418
end
404419

tests/test_jump.lua

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,12 @@ T['state']['updates `mode`'] = function()
183183

184184
type_keys('d', 't', 'e')
185185
eq(get_state().mode, 'nov')
186+
type_keys('V', 't', 'e')
187+
eq(get_state().mode, 'V')
188+
child.ensure_normal_mode()
189+
-- Ensure dot-repeat does not update mode after the jump
190+
type_keys('.')
191+
eq(get_state().mode, 'V')
186192
child.lua('MiniJump.stop_jumping()')
187193
end
188194

@@ -402,7 +408,7 @@ T['Jumping with f/t/F/T']['works in Operator-pending mode'] = new_set({
402408
type_keys('d', '2', key, 'e')
403409
eq(get_lines(), { line_seq[3] })
404410

405-
-- Just typing `key` shouldn't repeat action
411+
-- Just typing `key` shouldn't repeat motion
406412
local cur_pos = get_cursor()
407413
type_keys(key)
408414
eq(get_cursor(), cur_pos)
@@ -582,6 +588,32 @@ T['Jumping with f/t/F/T']['can be dot-repeated if did not jump at first'] = func
582588
validate('dT', 1, 5, 'abcdg')
583589
end
584590

591+
T['Jumping with f/t/F/T']['inside dot-repeat is not affected by regular jumping'] = function()
592+
-- Normal mode
593+
local validate = function(keys, key_antagonist, result)
594+
local line = '_xdxdx1x1xdxdx_'
595+
local tests_forward = key_antagonist == string.upper(key_antagonist)
596+
597+
set_lines({ line })
598+
set_cursor(1, tests_forward and 0 or (string.len(line) - 1))
599+
600+
type_keys(keys)
601+
type_keys(tests_forward and '$' or '^')
602+
type_keys(key_antagonist, '1')
603+
type_keys('.')
604+
eq(get_lines(), { result })
605+
606+
-- Ensure there is no jumping
607+
child.lua('MiniJump.stop_jumping()')
608+
child.ensure_normal_mode()
609+
end
610+
611+
validate('2dfd', 'T', 'x1x1x_')
612+
validate('2dtd', 'F', 'dx1xdx_')
613+
validate('2dFd', 't', '_x1x1x')
614+
validate('2dTd', 'f', '_xdx1xd')
615+
end
616+
585617
T['Jumping with f/t/F/T']['stops prompting for target if hit `<Esc>` or `<C-c>`'] = new_set({
586618
parametrize = {
587619
{ 'f', '<Esc>' },
@@ -878,6 +910,26 @@ T['Repeat jump with ;']['works after jump in Operator-pending mode'] = function(
878910
type_keys('d', '2f', 'e', ';')
879911
eq(get_lines(), { '3e4e5e' })
880912
eq(get_cursor(), { 1, 3 })
913+
914+
-- Like nvim --clean, it does not use the latest dot repeat
915+
set_lines({ '1e2e3e3e4e5e6' })
916+
set_cursor(1, 0)
917+
918+
type_keys('d', '2f', 'e')
919+
eq(get_lines(), { '3e3e4e5e6' })
920+
eq(get_cursor(), { 1, 0 })
921+
922+
type_keys('$', 'T', '3')
923+
eq(get_lines(), { '3e3e4e5e6' })
924+
eq(get_cursor(), { 1, 3 })
925+
926+
type_keys('.')
927+
eq(get_lines(), { '3e36' })
928+
eq(get_cursor(), { 1, 3 })
929+
930+
type_keys(';')
931+
eq(get_lines(), { '3e36' })
932+
eq(get_cursor(), { 1, 1 })
881933
end
882934

883935
T['Repeat jump with ;']['works in Operator-pending mode'] = function()

0 commit comments

Comments
 (0)