Vim переключение буфера перезаписывает поведение при удалении

Vim отлично, но, как и многие люди, я очень раздражаюсь, когда хочу скопировать, удалить, а затем вставить - буфер yank перезаписывается действием удаления.

Теперь я знаю, что есть 101 work-arounds и сопоставления, некоторые из которых перечислены в сообщениях, подобных этому: Любой способ удалить в vim без перезаписи вашего последнего yank?

Но у всех этих решений есть недостатки - даже я был буфером-гуру (которого я не знаю). Например, избыточные нажатия клавиш - в то время как я обычно xxxx, чтобы быстро удалить 4 символа (только одно нажатие клавиши, потому что я держу его и жду авторежима), мне небезопасно переключаться на x, x, x, x или независимо от отображения, мне нужно использовать другой буфер.

То, что действительно было бы идеальным, - это просто режим переключения, посредством которого вы можете включать и отключать поведение побочных эффектов клавиш D, d, X и x, чтобы они поочередно выполняли или не записывали свой текст в буфер. Таким образом, я могу просто ввести режим "без побочных эффектов" и удалить его до содержания сердца, а затем вставить, когда я буду готов. При необходимости снова включите побочные эффекты.

Кто-нибудь знает, как это сделать?

[UPDATE: SOLUTION] OK У меня получилось: я написал функцию, которая переключает режим "без побочных эффектов"... отлично работает! См. Мой принятый правильный ответ ниже

[UPDATE # 2] Мое решение все еще отлично работает, и я использую его все время, когда я делаю много удаления и вставки. Но тем временем я также нашел более легкий способ удовлетворить конкретный вариант использования копии, вставки, удаления для простых случаев, когда текст для удаления является смежным.

После нормального поиска текста я затем визуально выделяю текст для удаления с помощью команды v, а затем просто вставляю его с помощью команды p. Это обеспечивает желаемый эффект без какого-либо специального отображения.

Единственная проблема с этим документооборотом заключается в том, что если я захочу вставить снова, оригинальный буфер вставки будет перезаписан актом вставки над выделенным текстом, но это поведение легко изменить с помощью следующего отображения в .vimrc:

vnoremap p "_dp
vnoremap P "_dP

Ответ 1

ОК, я понял - этот script в .vimrc позволяет мне эффективно переключать режим "без побочных эффектов", в результате чего ключи d и x больше не перезаписывают буфер, когда режим "без буферных побочных эффектов" активируется.

Добавьте это в .vimrc

function! ToggleSideEffects()
    if mapcheck("dd", "n") == ""
        noremap dd "_dd
        noremap D "_D
        noremap d "_d
        noremap X "_X
        noremap x "_x
        echo 'side effects off'
    else
        unmap dd
        unmap D
        unmap d
        unmap X
        unmap x
        echo 'side effects on'
    endif
endfunction
nnoremap ,, :call ToggleSideEffects()<CR>

Затем для переключения в и из этого режима используйте комбинацию клавиш (две запятые)

Ответ 2

Я думаю, что попытка "выключить" побочные эффекты для каждой команды удаления/изменения будет слишком сложной, если не невозможной. Основные способы решения этой проблемы:

  • Используйте регистр черного дыра ("_) с помощью команд удаления или изменения. например "_dd
  • Используйте регистр "0, который содержит самый последний yank с вашими командами вставки. например "0p
  • Сохранение текста в названный регистр. например "ayy, а затем выполните "ap

Я лично склоняюсь к подходу "0p, поскольку это соответствует тому, как работает мой ум.

Теперь, увидев, что вы не задали таких обходов, я предоставил некоторые функции, которые изменяют команды вставки для переключения между так называемыми режимами paste_copy и nopaste_copy. nopaste_copy является поведением по умолчанию Vim. Поместите в ~/.vimrc следующее:

function! PasteCopy(cmd, mode)
  let reg = ""
  if exists('g:paste_copy') && g:paste_copy == 1 && v:register == '"'
    let reg = '"0'
  elseif v:register != '"'
    let reg = '"' . v:register
  endif
  let mode = ''
  if a:mode == 'v'
    let mode = 'gv'
  endif
  exe "norm! " . mode . reg . a:cmd
endfunction

command! -bar -nargs=0 TogglePasteCopy let g:paste_copy = exists('g:paste_copy') && g:paste_copy == 1 ? 0 : 1<bar>echo g:paste_copy ? '  paste_copy' : 'nopaste_copy'

nnoremap <silent> p :call PasteCopy('p', 'n')<cr>
nnoremap <silent> P :call PasteCopy('P', 'n')<cr>
nnoremap <silent> ]p :call PasteCopy(']p', 'n')<cr>
nnoremap <silent> [p :call PasteCopy('[p', 'n')<cr>
nnoremap <silent> ]P :call PasteCopy(']P', 'n')<cr>
nnoremap <silent> [P :call PasteCopy('[P', 'n')<cr>
vnoremap <silent> p :<c-u>call PasteCopy('p', 'v')<cr>
vnoremap <silent> P :<c-u>call PasteCopy('P', 'v')<cr>

Вы можете переключить режим paste_copy с помощью :TogglePasteCopy. Вы можете предпочесть отображение таким образом

nnoremap <leader>tp :TogglePasteCopy<cr>

В качестве заключительного совета я бы настоятельно предложил использовать "0p или использовать именованный регистр для этого подхода, поскольку они являются родными для vim, и есть один менее "режим", о котором можно беспокоиться.