vim toggling buffer overwrite behavior when deleting

前端 未结 2 1910
粉色の甜心
粉色の甜心 2020-12-11 08:38

Vim is great, but like many people I get really annoyed when I want to copy, delete, then paste -- the yank buffer gets overwritten by the delete action.

Now I know

相关标签:
2条回答
  • 2020-12-11 09:11

    OK, I got it -- this script in .vimrc lets me effectively toggle a "no buffer side-effects" mode whereby the d and x keys no longer overwrite the buffer when "no buffer side-effects" mode is activated.

    Add this in .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>
    

    Then to toggle in and out of this mode use the key combination ,, (two commas)

    0 讨论(0)
  • 2020-12-11 09:12

    I think trying to "turn-off" the side effects for every delete/change command would be overly difficult if not impossible. The basic ways to handle this situation:

    • Use the black hole ("_) register with your delete or change commands. e.g. "_dd
    • Use the "0 register which contains the most recent yank with your paste commands. e.g. "0p
    • Yanking the text to a named register. e.g. "ayy then later doing "ap

    I personally lean toward the "0p approach as this is fits with how my mind works.

    Now seeing you asked for no such work-arounds I have provided some functions that alter the paste commands to toggle between my so called paste_copy and nopaste_copy mode. nopaste_copy being Vim's default behavior. Put the following in your ~/.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>
    

    You can toggle your paste_copy mode via :TogglePasteCopy. You may prefer a mapping like so

    nnoremap <leader>tp :TogglePasteCopy<cr>
    

    As a closing piece of advice I would highly suggest using "0p or using a named register over this approach as they are native to vim and there is one less "mode" to worry about.

    0 讨论(0)
提交回复
热议问题