25

Here's how I usually copy a block of text or code:

  1. Select the block with Visual mode (V) and delete it with d; or if it's just a single line, just use dd.
  2. Go to where I want the text to be, I am too stupid to remember the difference between p and P, so I get this right about 50% of time. (if I get it wrong: undo a try again).
  3. Sometimes, the indentation needs adjusting, so I go to Visual mode with V again and reselect the same block, and use > or < to fix that.

Is there an easier way? In some editors I've seen that you can "pick up" a block of text, as it were, and move it around; here's an example from Emacs (but I've also seen this in other editors):

Emacs

Or perhaps there is another (even better) way?

  • About the indentation issue you can solve it by pasting with ]p or [p rather than p or P. This way the block that you paste will be autoindented. – Gonçalo Ribeiro Feb 8 '15 at 0:28
  • You might want to watch the screencast by Drew Neil Bubbling Text which recommends to use vim-unimpaired. – Hotschke Apr 12 '18 at 16:22
13

There's a plugin for that: dragvisuals.vim.

It doesn't bind any keys by default, so you'll have to do that yourself. I like to map them to Control+Arrow key:

xmap <expr> <C-Left> DVB_Drag('left')
xmap <expr> <C-Right> DVB_Drag('right')
xmap <expr> <C-Down> DVB_Drag('down')
xmap <expr> <C-Up> DVB_Drag('up')

It also comes with a bonus key to duplicate the current selection:

xmap <expr> D DVB_Duplicate()

Advantages of this plugin over the other answers:

  • Doesn't make any text disappear if you try to move further up than the first line.
  • It will expand the file if you move below the last line.
  • Moving to the left/right works a bit better.

Another useful trick to complement this, are these keybinds:

xnoremap > >gv
xnoremap < <gv

This will re-select the last visual selection after you use > while in Visual mode, so you can adjust the alignment more easily (you can also use the arrow keys, but this will move it by one character, and not one shiftwidth).

8

For step 3, you can use gv= instead (= means indent, and gv means "reselect last visual selection").

For the Emacs behavior, it'd be pretty simple to add some mappings in your .vimrc:

vnoremap <down> dpV`]
vnoremap <up> dkPV`]

You can then use the up and down arrow keys to move around a visual line selection. (Of course, you could map to different keys as well if you hate arrows.)

(You could do this with normal visual selections and moving them left and right too: vnoremap <left> dhPgvhoho and vnoremap <right> dpgvlolo.)

  • gv goes to the last visual selection, which in this case would be the paragraph that was deleted. What am I missing? – Robert Smith Feb 8 '15 at 1:36
4

You can remap some keys to move lines around. For example, arrows up and down if you are used to move around through hjkl.

E.g on .vimrc

nnoremap <down> :m .+1<CR>==
nnoremap <up> :m .-2<CR>==
vnoremap <down> :m '>+1<CR>gv=gv
vnoremap <up> :m '<-2<CR>gv=gv

:m, normal command to move a line

+1 or -2 to indicate a line up or down (-1 keeps the line on the same place)

gv to select again the same text in VISUAL mode

This solution does not interfere with the registers, so any copied text will still be available, as well as reformat the code to set proper indentation, etc.

  • This is nice, but not for me, since I don't like using = (it often changes too much unrelated formatting for me). – Martin Tournoij Feb 8 '15 at 21:16
3

The easiest way I found to do this is documented here: http://vimrcfu.com/snippet/77

Put the following in your .vimrc

vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv
3

There are few plugins for this but I prefer Tim Pope's vim-unimpaired (github) (Ingo Karkat LineJuggler is similar).

You visually select your block of text then do ]e (e for exchange) to move the block downwards ([e for the other direction). Use . to repeat the action (You do have repeat.vim installed don't you). If you go too far then just undo via u.

Now personally I think p and P are such common commands that it would be best to learn them before creating bad habits. Then you could use ]p to paste at the same indent. If you are using unimpaired you can do >p to paste an indention level deeper or =p to paste and reformat.

If you have trouble remembering p and P then it might help you to think of them in terms of the o and O commands which is a kind of symmetry.

As others have noted you can use gv to reselect a visual selection. However if you just put/pasted text you will have lost your visual selection. Don't fret because every change (and yanks!) will set '[ and '] around the changed area. So you can indent via >'] (read: shift right until end of last change) and use the . to repeat the indention until you have the text in the right spot.

For more help see:

:h p
:h P
:h ]p
:h o
:h O
:h .
:h u
:h >
:h ']
:h gv
2

If you know the line number that you want to move the block of text to, then you can use a range or visual selection with the :move command to move the block to there.

For example, if I have the following file:

1 aaa
2 bbb
3 ccc
4 ddd

and I want to move the line of a's to after the line of c's, I put the cursor on the line of a's and enter :m3, and the line is then shifted.

This also works with +/- offsets. In the example above, the same result could be accomplished with :m+2 to move the line 2 lines down.

For blocks of text, the only difference is adding in a range or selection. To move the aaa and bbb lines to the end of the file, use a command like :1,2m$ ($ = last line) or visually select the lines and :m$.

1

Plugin vim-move by matze

Available from

  1. https://www.vim.org/scripts/script.php?script_id=4687
  2. https://github.com/matze/vim-move

Default mappings in visual and normal mode:

<A-k>   Move current line/selection up
<A-j>   Move current line/selection down

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.