How to emulate Emacs’ transpose-words in Vim?

There's a tip on http://vim.wikia.com/wiki/VimTip10. But I choose to roll my own. My snippet has two obvious advantages over the method mentioned in the tip: 1) it works when the cursor isn't in a word. 2) it won't high-light the entire screen.

It works almost like emacs 'transpose-words', except that when transposition is impossible, it does nothing. (emacs 'transpose-words' would blink and change cursor position to the beginning of current word.)

"transpose words (like emacs `transpose-words')
function! TransposeWords()
    if search('\w\+\%#\w*\W\+\w\+')
    elseif search('\w\+\W\+\%#\W*\w\+')
    endif
    let l:pos = getpos('.')
    exec 'silent! :s/\(\%#\w\+\)\(\W\+\)\(\w\+\)/\3\2\1/'
    call setpos('.', l:pos)
    let l:_ = search('\(\%#\w\+\W\+\)\@<=\w\+')
    normal el
endfunction

nmap <silent> <M-right> :call TransposeWords()<CR>
imap <silent> <M-right> <C-O>:call TransposeWords()<CR>

Depending on the situation, you can use the W or B commands, as in dWwP. The "capital" versions skip to the next/previous space, including punctuation. The f and t commands can help, as well, for specifying the end of the deleted range.

There's also a discussion on the Vim Tips Wiki about various swapping techniques.


In the middle of a line, go to the first letter of the first word, then do

dw wP

At the end of a line (ie the last two words of the line), go to the space between the words and do

2dw bhP

From the handy Equivalence of VIM & Emacs commands


You could add shortcut keys for those by adding something like the following to your vimrc file:

map L dwwP
map M 2dwbhP 

In that case, SHIFT-L (in command-mode) would switch words in the middle of the line and SHIFT-M would do it at the end.

NB: This works best with space-separated words and doesn't handle the OP's specific case very well.


These are from my .vimrc and work well for me.

" swap two words
:vnoremap <C-X> <Esc>`.``gvP``P
" Swap word with next word
nmap <silent> gw    "_yiw:s/\(\%#\w\+\)\(\_W\+\)\(\w\+\)/\3\2\1/<cr><c-o><c-l> *N*