Как подражать Emacs транспонировать слова в Vim?

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 обменял бы b и c, в результате получив (a)(c)(b).

Что работает /\w yiwNviwpnviwgp. Но это портит "" и "/. Есть ли более чистое решение?

Update²:

решаемые

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

Несовершенно, но работает.

Спасибо Camflan за то, что вы принесли мне элемент %#. Конечно, все это на wiki, но я не понимал, что он может решить проблему точного (Emacs получил полное право) дублирование transpose-words.

Ответы

Ответ 1

Это из моего .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*

Ответ 2

В зависимости от ситуации вы можете использовать команды W или B, как в dWwP. "Капитальные" версии пропускают до следующего/предыдущего места, включая знаки препинания. Команды f и t также могут помочь в определении конца удаленного диапазона.

Здесь также обсуждается Vim Tips Wiki о различных методах замены.

Ответ 3

В середине строки перейдите к первой букве первого слова, затем выполните

dw wP

В конце строки (т.е. последние два слова строки) перейдите в пространство между словами и сделайте

2dw bhP

Из удобного Эквивалентность команд VIM и Emacs


Вы можете добавить для них сочетания клавиш, добавив в файл vimrc что-то вроде следующего:

map L dwwP
map M 2dwbhP 

В этом случае SHIFT-L (в командном режиме) переключит слова в середине строки, а SHIFT-M сделает это в конце.

NB: Это лучше всего работает с словами, разделенными пробелами, и не очень хорошо справляется с конкретным случаем OP.

Ответ 4

Вот отзыв на http://vim.wikia.com/wiki/VimTip10. Но я решил бросить свою. У моего фрагмента есть два очевидных преимущества по методу, указанному в подсказке: 1) он работает, когда курсор не находится в одном слове. 2) он не будет подсветить весь экран.

Он работает почти как "транспонированные слова" emacs, за исключением того, что когда транспонирование невозможно, оно ничего не делает. (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>

Ответ 5

Вы можете использовать dwwP или dWwP, как сказали Mark и CapnNefarious, но у меня есть несколько собственных нот:

  • Если курсор находится на первой букве второго слова, как в примере, который вы дали, вы можете использовать dwbP (или dWbP для обработки пунктуации);
  • Если курсор находится в середине слова, вы можете использовать dawbP/daWbP.