Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions lua/mini/jump.lua
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ MiniJump.state = {
MiniJump.jump = function(target, backward, till, n_times)
if H.is_disabled() then return end

-- If dot-repeating the state needs to be restored after the jump
local needs_restore = MiniJump._is_expr and MiniJump.state.mode ~= 'no'
MiniJump._is_expr = nil
local state_snapshot = needs_restore and vim.deepcopy(MiniJump.state) or nil

-- Cache inputs for future use
H.update_state(target, backward, till, n_times)

Expand Down Expand Up @@ -230,6 +235,12 @@ MiniJump.jump = function(target, backward, till, n_times)
-- Track cursor position to account for movement not caught by `CursorMoved`
H.cache.latest_cursor = H.get_cursor_data()
H.cache.has_changed_cursor = not vim.deep_equal(H.cache.latest_cursor, init_cursor_data)

-- If dot-repeating restore the state to its value from before this jump
if needs_restore then
state_snapshot.jumping = true
MiniJump.state = state_snapshot
end
end

--- Make smart jump
Expand Down Expand Up @@ -383,7 +394,8 @@ H.make_expr_jump = function(backward, till)
return function()
if H.is_disabled() then return '' end

H.update_state(nil, backward, till, vim.v.count1)
local count = vim.v.count1
H.update_state(nil, backward, till, count)

-- Ask for `target` for non-repeating jump as this will be used only in
-- operator-pending mode. Dot-repeat is supported via expression-mapping.
Expand All @@ -398,7 +410,10 @@ H.make_expr_jump = function(backward, till)
if H.cache.has_changed_cursor then return end
vim.cmd('undo!')
end)
return 'v<Cmd>lua MiniJump.jump()<CR>'

-- Encode state in expression for dot-repeat
local args = string.format('%s,%s,%s,%s', vim.inspect(target), backward, till, count)
return 'v<Cmd>lua MiniJump._is_expr=true; MiniJump.jump(' .. args .. ')<CR>'
end
end

Expand Down
54 changes: 53 additions & 1 deletion tests/test_jump.lua
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ T['state']['updates `mode`'] = function()

type_keys('d', 't', 'e')
eq(get_state().mode, 'nov')
type_keys('V', 't', 'e')
eq(get_state().mode, 'V')
child.ensure_normal_mode()
-- Ensure dot-repeat does not update mode after the jump
type_keys('.')
eq(get_state().mode, 'V')
child.lua('MiniJump.stop_jumping()')
end

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

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

T['Jumping with f/t/F/T']['inside dot-repeat is not affected by regular jumping'] = function()
-- Normal mode
local validate = function(keys, key_antagonist, result)
local line = '_xdxdx1x1xdxdx_'
local tests_forward = key_antagonist == string.upper(key_antagonist)

set_lines({ line })
set_cursor(1, tests_forward and 0 or (string.len(line) - 1))

type_keys(keys)
type_keys(tests_forward and '$' or '^')
type_keys(key_antagonist, '1')
type_keys('.')
eq(get_lines(), { result })

-- Ensure there is no jumping
child.lua('MiniJump.stop_jumping()')
child.ensure_normal_mode()
end

validate('2dfd', 'T', 'x1x1x_')
validate('2dtd', 'F', 'dx1xdx_')
validate('2dFd', 't', '_x1x1x')
validate('2dTd', 'f', '_xdx1xd')
end

T['Jumping with f/t/F/T']['stops prompting for target if hit `<Esc>` or `<C-c>`'] = new_set({
parametrize = {
{ 'f', '<Esc>' },
Expand Down Expand Up @@ -878,6 +910,26 @@ T['Repeat jump with ;']['works after jump in Operator-pending mode'] = function(
type_keys('d', '2f', 'e', ';')
eq(get_lines(), { '3e4e5e' })
eq(get_cursor(), { 1, 3 })

-- Like nvim --clean, it does not use the latest dot repeat
set_lines({ '1e2e3e3e4e5e6' })
set_cursor(1, 0)

type_keys('d', '2f', 'e')
eq(get_lines(), { '3e3e4e5e6' })
eq(get_cursor(), { 1, 0 })

type_keys('$', 'T', '3')
eq(get_lines(), { '3e3e4e5e6' })
eq(get_cursor(), { 1, 3 })

type_keys('.')
eq(get_lines(), { '3e36' })
eq(get_cursor(), { 1, 3 })

type_keys(';')
eq(get_lines(), { '3e36' })
eq(get_cursor(), { 1, 1 })
end

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