如何在Vim中模拟Emacs的transpose-words功能?

16

Emacs有一个实用的transpose-words命令,它允许用户交换光标前面的单词和后面的单词,并保留标点符号。

例如,‘stack |overflow’ + M-t = ‘overflow stack|’(‘|’是光标位置)。

<a>|<p>变成了<p><a|>

在Vim中是否可能模拟这个功能?我知道我可以使用dwwP,但它在处理标点方面效果不佳。

更新:不,dwwP真的不是一个解决方案。想象一下:

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

Emacs的M-t会交换bc,导致结果是(a)(c)(b)

可行的方法是/\w yiwNviwpnviwgp。但它破坏了"""/。有更简洁的解决方案吗?

更新²:

已解决

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

还有不足之处,但是能用。

感谢Camflan提醒我%#这个东西。当然,这都写在维基上了,但我并没有意识到它可以解决精确地(Emacs做到了完全正确)复制transpose-words功能的问题。


我在谷歌上搜索"%#"时遇到了困难。这里它们代表什么? - Thomas G Henry
使用内置的 Vim 帮助::h /%# - Roman Odaisky
6个回答

7

这些是我 .vimrc 文件中的内容,对我来说很有效。

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

谢谢,我真的很喜欢这个可视化地图。但要注意的是,由于标记的列数不会改变,因此,如果您要交换的两个单词在同一行上,则必须从左侧删除第一个单词,然后再从左侧<C-X>第二个单词,而不是反过来(当两个单词实际上具有相同长度时除外)。 - Giles Gardam

5

根据情况,您可以使用W或B命令,例如dWwP。大写版本跳到下一个/上一个空格,包括标点符号。f和t命令也可以帮助指定删除范围的结尾。

还有一个关于各种交换技巧的讨论在Vim Tips Wiki上。


5
在一行的中间,移动到第一个单词的第一个字母,然后执行。
dw wP

在一行的末尾(即该行的最后两个单词),移动到单词之间的空格并执行以下操作:

2dw bhP

来源于方便的 VIM和Emacs命令对等表


您可以通过在vimrc文件中添加以下内容来为这些命令添加快捷键:

map L dwwP
map M 2dwbhP 

在这种情况下,SHIFT-L(在命令模式中)会在行中间切换单词,而SHIFT-M则会在末尾执行。注意:这种方法最适用于以空格分隔的单词,并且不太适用于OP的特定情况。

2
这里有一个关于Vim编辑器的技巧,可以在http://vim.wikia.com/wiki/VimTip10上找到。但我选择自己编写代码。
我的代码比这个技巧提到的方法有两个明显的优点:1)当光标不在单词中时也能正常工作。2)不会高亮整个屏幕。
它的工作原理类似于emacs的“transpose-words”,但是当无法交换单词时,它将不执行任何操作(emacs的“transpose-words”会闪烁并将光标位置更改为当前单词的开头)。
"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>

0

0

你可以像Mark和CapnNefarious所说的那样使用dwwP或dWwP,但我有一些自己的注释:

  • 如果光标在第二个单词的第一个字母上,就像你给出的例子一样,你可以使用dwbP(或dWbP来处理标点符号);
  • 如果光标在单词中间,你可以使用dawbP/daWbP。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接