如何模拟 Emacs Vim 中的转置单词?

发布于 2024-07-06 01:53:19 字数 1072 浏览 6 评论 0原文

Emacs 有一个有用的 transpose-words 命令,它可以让我们将光标之前的单词与光标之后的单词交换,从而保留标点符号。

例如,'stack |overflow' + Mt = 'overflow stack|'('|' 是光标位置)。

|

变为

可以在 Vim 中模拟吗? 我知道我可以使用 dwwP,但它不能很好地处理标点符号。

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

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

Emacs 的 Mt 会交换 bc,从而得到 (a)(c)(b)

有效的是 /\w yiwNviwpnviwgp。 但它破坏了 """/。有更干净的解决方案吗?

更新²:

解决了

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

不完美,但有效。

感谢 Camflan 带来< code>%# 项目引起了我的注意,当然,这些都在 wiki 上。 ,但我没有意识到它可以解决 transpose-words 功能的精确(Emacs 完全正确)重复的问题。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

千寻… 2024-07-13 01:53:19

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

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*
太傻旳人生 2024-07-13 01:53:19

vim.org 上有一个转置单词脚本,效果非常好。

There's a transpose-words script on vim.org that works beautifully.

空城仅有旧梦在 2024-07-13 01:53:19

您可以使用 dwwP 或 dWwP 正如 Mark 和 CapnNefious 所说,但我有一些自己的注释:

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

You can use dwwP or dWwP as Mark and CapnNefarious have said, but I have a few notes of my own:

  • If the cursor is on the first letter of the second word, as in the example you gave, you can use dwbP (or dWbP to handle punctuation);
  • If the cursor is in the middle of the word, you can use dawbP/daWbP.
那片花海 2024-07-13 01:53:19

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>

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>
昨迟人 2024-07-13 01:53:19

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

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

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.

天荒地未老 2024-07-13 01:53:19

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

dw wP

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

2dw bhP

从方便 VIM 和 VIM 的等效项 Emacs 命令


您可以通过在 vimrc 文件中添加类似以下内容来添加快捷键:

map L dwwP
map M 2dwbhP 

在这种情况下,SHIFT-L(在命令模式下)将在行中间切换单词SHIFT-M 将在最后执行此操作。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文