【问题标题】:How to emulate Emacs’ transpose-words in Vim?如何在 Vim 中模拟 Emacs 的转置词?
【发布时间】:2010-09-13 13:43:25
【问题描述】:

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 让我注意到 %# 项目。当然,这一切都在wiki 上,但我没有意识到它可以解决transpose-words 功能的精确(Emacs 完全正确)重复的问题。

【问题讨论】:

  • 我很难用谷歌搜索“%#”。它们在这里意味着什么?
  • 使用内置的 Vim 帮助: :h /\%#

标签: vim emacs editor usability


【解决方案1】:

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

Vim Tips Wiki 上也有关于各种交换技术的讨论。

【讨论】:

    【解决方案2】:

    在一行的中间,到第一个单词的第一个字母,然后做

    dw wP
    

    在一行的末尾(即该行的最后两个单词),到单词之间的空格处做

    2dw bhP
    

    来自方便的Equivalence of VIM & Emacs commands


    您可以通过在您的 vimrc 文件中添加如下内容来为它们添加快捷键:

    map L dwwP
    map M 2dwbhP 
    

    在这种情况下,SHIFT-L(在命令模式下)会在行的中间切换单词,而 SHIFT-M 会在最后进行。

    注意:这最适用于空格分隔的单词,并且不能很好地处理 OP 的特定情况。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        这些来自我的 .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*
        

        【讨论】:

        • 谢谢,我真的很喜欢可视化地图。但是需要注意的是,由于标记的列号不会改变,如果您要交换的两个单词在同一行,那么您必须从删除第一个单词开始left 然后 从左数第二个单词,而不是相反(例外情况是两个单词实际上长度相同)。
        【解决方案5】:

        http://vim.wikia.com/wiki/VimTip10 上有一个提示。但我选择自己动手。 我的 sn-p 比提示中提到的方法有两个明显的优势: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>
        

        【讨论】:

          【解决方案6】:

          vim.org 上有一个 transpose-words script,效果很好。

          【讨论】:

            猜你喜欢
            • 2010-11-29
            • 2010-10-10
            • 1970-01-01
            • 1970-01-01
            • 2012-01-11
            • 1970-01-01
            • 1970-01-01
            • 2012-03-15
            • 1970-01-01
            相关资源
            最近更新 更多