Search code examples
vimemacseditorusability

How to emulate Emacs’ transpose-words in Vim?


Emacs has a useful transpose-words command which lets one exchange the word before the cursor with the word after the cursor, preserving punctuation.

For example, ‘stack |overflow’ + M-t = ‘overflow stack|’ (‘|’ is the cursor position).

<a>|<p> becomes <p><a|>.

Is it possible to emulate it in Vim? I know I can use dwwP, but it doesn’t work well with punctuation.

Update: No, dwwP is really not a solution. Imagine:

SOME_BOOST_PP_BLACK_MAGIC( (a)(b)(c) )
//             with cursor here ^

Emacs’ M-t would have exchanged b and c, resulting in (a)(c)(b).

What works is /\w yiwNviwpnviwgp. But it spoils "" and "/. Is there a cleaner solution?

Update²:

Solved

:nmap gn :s,\v(\w+)(\W*%#\W*)(\w+),\3\2\1\r,<CR>kgJ:nohl<CR>

Imperfect, but works.

Thanks Camflan for bringing the %# item to my attention. Of course, it’s all on the wiki, but I didn’t realize it could solve the problem of exact (Emacs got it completely right) duplication of the transpose-words feature.


Solution

  • 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*