Skip to content

Commit

Permalink
use :undojoin to merge subsequent moves into one
Browse files Browse the repository at this point in the history
  • Loading branch information
jedrzejboczar committed Dec 14, 2021
1 parent 6442747 commit ba112e7
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ normal mode:
The mappings can be prefixed with a count, e.g. `5<A-k>` will move the selection
up by 5 lines.

Features:

* vertical motions
* horizontal motions
* automatic indentation
* undo multiple moves with single `:undo`

See this short demo for a first impression:

![vim-vertical-move demo](http://i.imgur.com/RMv8KsJ.gif)
Expand Down
10 changes: 10 additions & 0 deletions doc/move.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ the line. Can be disabled with >
let g:move_past_end_of_line = 0
By default subsequent move operations in the same direction use |:undojoin| so
that all of them are undone after hitting |:undo| once. Can be disabled with >
let g:move_undo_join = 0
It is also possible to uses |:undojoin| for all moves, regardless of motion
direction with >
let g:move_undo_join_same_dir_only = 0
-------------------------------------------------------------------------------
2.1 <Plug>MoveBlockDown

Expand Down
40 changes: 40 additions & 0 deletions plugin/move.vim
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,30 @@ if !exists('g:move_past_end_of_line')
let g:move_past_end_of_line = 1
endif

if !exists('g:move_undo_join')
let g:move_undo_join = 1
endif

if !exists('g:move_undo_join_same_dir_only')
let g:move_undo_join_same_dir_only = 1
endif

function s:UndoJoin(dir)
" Check changedtick to see if there were no other changes since our last
" operation. Dending on settings we may also require the same dir of move.
let l:last = get(b:, 'move_last', { 'changedtick': -1, 'dir': v:null })
let l:no_changes = l:last.changedtick == b:changedtick
let l:dir_ok = g:move_undo_join_same_dir_only == 0 || l:last.dir == a:dir
if l:no_changes && l:dir_ok
silent! undojoin
endif
endfunction

function s:SaveMoveInfo(dir)
" Save changedtick/dir to check it in the next move operation.
let b:move_last = { 'changedtick': b:changedtick, 'dir': a:dir }
endfunction

"
" Move and possibly reindent the given lines.
" Goes down if (distance > 0) and up if (distance < 0).
Expand Down Expand Up @@ -58,6 +82,10 @@ function s:MoveVertically(first, last, distance)
" across a folded section causes it to unfold.
call setpos('.', l:old_pos)

if g:move_undo_join
call s:UndoJoin(a:distance < 0 ? 'up' : 'down')
endif

" After this :move the '[ and '] marks will point to first and last moved
" line and the cursor will be placed at the last line.
execute l:first ',' l:last 'move' l:after
Expand Down Expand Up @@ -91,6 +119,10 @@ function s:MoveVertically(first, last, distance)
call cursor(l:last, 1)
normal! $m]
endif

if g:move_undo_join
call s:SaveMoveInfo(a:distance < 0 ? 'up' : 'down')
endif
endfunction

"
Expand Down Expand Up @@ -151,6 +183,10 @@ function s:MoveHorizontally(corner_start, corner_end, distance)
return 0
endif

if g:move_undo_join
call s:UndoJoin(a:distance < 0 ? 'left' : 'right')
endif

let l:old_default_register = @"
normal! x

Expand All @@ -169,6 +205,10 @@ function s:MoveHorizontally(corner_start, corner_end, distance)
let &virtualedit = l:old_virtualedit
let @" = l:old_default_register

if g:move_undo_join
call s:SaveMoveInfo(a:distance < 0 ? 'left' : 'right')
endif

return 1
endfunction

Expand Down

0 comments on commit ba112e7

Please sign in to comment.