Como faço para substituir e colar o texto arrancado no vim sem arrancar as linhas excluídas?

29

Por isso, normalmente, encontro-me a copiar texto de um ponto para outro enquanto sobrescrevo texto antigo onde o novo é colado:

blah1
newtext
blah2
wrong1
blah3
wrong2
blah4

Suponha que eu marque a marca visual newtext e y ank. Agora, seleciono wrong1 (que pode ser qualquer coisa, não necessariamente apenas uma palavra) e p aste newtext . No entanto, se eu fizer o mesmo com wrong2 , ele será substituído por wrong1 em vez de newtext .

Então, como manter o texto que está no buffer de ser trocado com o texto que estou sobrescrevendo atualmente?

Editar 1

Embora eu goste bastante das sugestões de re-registro (acho que vou começar a usar mais registros, agora que descobri o comando :dis ), vou com uma modificação de jinfield 's resposta, porque eu faço não use o modo de troca.

vnoremap p "0p
vnoremap P "0P
vnoremap y "0y
vnoremap d "0d

faz o truque perfeitamente.

Editar 2

Eu estava muito rápido; A solução do romainl é precisamente o que eu estava procurando, sem o hack em Editar 1 .
Na verdade, vnoremap p "_dP é suficiente!
Então, mudando a resposta aceita.

    
por bitmask 10.08.2011 / 21:39

9 respostas

15

Eu tenho esses mapeamentos no meu .vimrc:

" delete without yanking
nnoremap <leader>d "_d
vnoremap <leader>d "_d

" replace currently selected text with default register
" without yanking it
vnoremap <leader>p "_dP

"_ é o "registro blackhole", de acordo com :help "_ :

"Ao escrever para este registro, nada acontece. Isto pode ser usado para deletar texto sem afetar os registros normais. Ao ler deste registro, nada é retornado. {not in Vi}"

    
por 11.08.2011 / 08:21
10

Além do buffer padrão, você pode extrair texto em buffers nomeados e, em seguida, colocar a partir desses buffers nomeados. Existem até 26 buffers nomeados que você pode usar (um para cada letra). Use aspas duplas e uma letra para acessar um buffer nomeado. Exemplos:

"dyy - Arranca a linha atual no buffer d.
"a7yy - Arranque as próximas sete linhas no buffer a.
"dP - Coloque o conteúdo do buffer d antes do cursor.
"ap - Coloque o conteúdo do buffer a após o cursor

Outra coisa legal, se você usar uma letra maiúscula em vez de minúscula, isto é, "Dyy , a linha atual será anexada ao buffer d em vez de substituí-la. Mais detalhes no livro da O'Reilly: link

    
por 10.08.2011 / 22:13
4

Ao usar put no modo visual, o texto que você está substituindo, wrong1 , é substituído pelo conteúdo do registro 'unamed'.

Isso realmente funciona colocando o registrador após a seleção e, em seguida, excluindo a seleção. O problema é que essa exclusão agora é armazenada no registro unnamed e será usada para a próxima ação put .

A solução, de acordo com :h v_p , é inserir um registro nomeado, como "0y , e colar usando "0p o tempo necessário. Pode ser útil mapear <leader>y e <leader>p para usar um registro nomeado, se isso é algo que você faz com frequência.

:map <leader>y "0y
:map <leader>p "0p

para mais ajuda, consulte:

:help v_p
:help map
    
por 10.08.2011 / 23:29
3

Quando você puxa o texto para o registrador sem nome *, uma cópia também é colocada no registrador 0. Cada vez que você substitui o texto selecionado, você pode simplesmente colar o registrador 0. Veja

:help registers

Além disso, se você estiver substituindo um número de palavras com a mesma palavra, basta mover para o início da palavra a ser substituída e digitar . . Isso irá repetir a última operação de edição. Veja

:help single-repeat

* Os locais de armazenamento em que você puxa e coloca são chamados registradores. Um buffer é o que você edita, geralmente uma cópia de um arquivo do disco.

    
por 10.08.2011 / 23:03
3

É importante saber o registro de "0 , mas muitas vezes você deseja substituir muitas vezes. Se você fizer uma ação repetitiva, poderá usar o operador . , como mencionado por garyjohn. É explicado no wiki do vim :

yiw     yank inner word (copy word under cursor, say "first". Same as above).
...     Move the cursor to another word (say "second").
ciw<C-r>0   select "second", then replace it with "first" If you are at the start of the word then cw<C-r>0 is sufficient.
...     Move the cursor to another word (say "third").
.   select "third", then replace it with "first". 
    
por 24.09.2012 / 18:52
0

Eu preciso disso muitas vezes, eu escrevi um plugin para isso: ReplaceWithRegister .

Este plugin oferece um comando two-in-one gr que substitui o texto coberto por {motion}, linha (s) inteira (s) ou a seleção atual pelo conteúdo de um registro; o texto antigo é excluído no registro do buraco negro, ou seja, desapareceu.

    
por 24.05.2012 / 14:33
0

Como algo como vnoremap p "_dP (eu também tentei x ou c ) tem problemas com início e fim da linha, acabei fazendo isso: vnoremap p :<C-U>let @p = @+<CR>gvp:let @+ = @p<CR> que eu achei mais simples que os plugins existentes (que também fizeram não funciona com set clipboard=unnamedplus fora da caixa). Então o que isso faz é:

  • mudar para o modo de comando
  • remover intervalo ( C-U )
  • backup + register (devido a unnamedplus, as alternativas são " e * dependendo da sua configuração) para p
  • recuperar seleção e colar
  • alterne para o modo de comando novamente
  • recuperar registro
por 13.01.2017 / 16:44
0

Isso é o que eu uso para o comportamento de colar do Windows, o que me permite selecionar visualmente o texto e colar o conteúdo da área de transferência para substituir o que foi selecionado, sem corromper o conteúdo da área de transferência no processo.

Nota: O código apresentado aqui é encurtado. Para uma listagem completa com capacidade de depuração e mais comentários e créditos, consulte: link

function! SmartCut()
    execute 'normal! gv"+c'

    if visualmode() != "\<C-v>" " If not Visual-Block mode
        " Trim the last \r\n | \n | \r character in the '+' buffer
        " Note: This messes up Visual-Block pasting.
        let @+ = substitute(@+,'\(\r\?\n\|\r\)$','','g')
    endif
endfunction

function! SmartCopy()
    execute 'normal! gv"+y'

    if visualmode() != "\<C-v>" " If not Visual-Block mode
        " Trim the last \r\n | \n | \r character in the '+' buffer
        " Note: This messes up Visual-Block pasting.
        let @+ = substitute(@+,'\(\r\?\n\|\r\)$','','g')
    endif
endfunction

function! SmartPaste()
    let mode = 'gv'

    let delete = '"_d'

    let reg = '"+'

    let currentLine = line(".")
    let lastLineOfBuffer = line("$")
    let selectionEndLine = line("'>")
    let selectionEndLineLength = len(getline(selectionEndLine))
    let nextLineLength = len(getline(currentLine + 1))
    let selectionEndColumn = col("'>")

    " If selection does not include or go beyond the last visible character of the line (by also selecting the invisible EOL character)
    if selectionEndColumn < selectionEndLineLength
        let cmd = 'P'

    " If attempting to paste on a blank last line
    elseif selectionEndLineLength == 0 && selectionEndLine == lastLineOfBuffer
        let cmd = 'P'

    " If selection ends after the last visible character of the line (by also selecting the invisible EOL character) and next line is not blank and not the last line
    elseif selectionEndColumn > selectionEndLineLength && nextLineLength > 0 && selectionEndLine != lastLineOfBuffer
        let cmd = 'P'

    " If selection ends after the last visible character of the line (by also selecting the invisible EOL character), or the line is visually selected (Shift + V), and next line is the last line
    elseif selectionEndColumn > selectionEndLineLength && selectionEndLine == lastLineOfBuffer
        let cmd = 'p'
        call append(selectionEndLine, "")

    else
        let cmd = 'p'
    endif

    if visualmode() != "\<C-v>" " If not Visual-Block mode
        " Trim the last \r\n | \n | \r character in the '+' buffer
        " Note: This messes up Visual-Block pasting.
        let @+ = substitute(@+,'\(\r\?\n\|\r\)$','','g')
    endif

    try
        execute 'normal! ' . mode . delete . reg . cmd
    catch /E353:\ Nothing\ in\ register\ +/
    endtry

    " Move caret one position to right
    call cursor(0, col(".") + 1)
endfunction

Uso:

" p or P delete to black hole register before pasting
vnoremap <silent>p :<C-u>call SmartPaste()<CR>
vnoremap <silent>P :<C-u>call SmartPaste()<CR>

" MiddleMouse delete to black hole register before pasting
nmap <MiddleMouse> "+p " Changes default behavior from 'P' mode to 'p' mode for normal mode middle-mouse pasting
vmap <silent><MiddleMouse> :<C-u>call SmartPaste()<CR>
imap <MiddleMouse> <C-r><C-o>+

" Disable weird multi-click things you can do with middle mouse button
map <2-MiddleMouse> <Nop>
imap <2-MiddleMouse> <Nop>
map <3-MiddleMouse> <Nop>
imap <3-MiddleMouse> <Nop>
map <4-MiddleMouse> <Nop>
imap <4-MiddleMouse> <Nop>


if os !~ "mac" " NOTE: MacVim provides Command+C|X|V|A|S and undo/redo support and also can Command+C|V to the command line by default
    " Copy and paste for the command line 
    cmap <C-c> <C-y>
    cmap <C-v> <C-r>+
    " TODO: Is their a select-all for the command line???

    vmap <silent><C-x> :<C-u>call SmartCut()<CR>
    vmap <silent><C-c> :<C-u>call SmartCopy()<CR>
    vmap <silent><C-v> :<C-u>call SmartPaste()<CR>
    imap <C-v> <C-r><C-o>+

    " Select-all support for normal, visual, and insert mode
    " http://vim.wikia.com/wiki/Using_standard_editor_shortcuts_in_Vim
    nmap <C-a> ggVG
    vmap <C-a> ggVG
    imap <C-a> <Esc>ggVG

    " Save file support for normal, visual, and insert mode
    " If the current buffer has never been saved, it will have no name,
    " call the file browser to save it, otherwise just save it.
    command -nargs=0 -bar Update if &modified |
                                \    if empty(bufname('%')) |
                                \        browse confirm write |
                                \    else |
                                \        confirm write |
                                \    endif |
                                \endif
    nmap <C-s> :update<CR>
    vmap <C-s> <Esc>:update<CR>V
    imap <C-s> <C-o>:update<CR>

    " Undo and redo support for normal, visual, and insert mode
    nmap <C-z> <Esc>u
    nmap <C-y> <Esc><C-r>

    vmap <C-z> <Esc>uV
    vmap <C-y> <Esc><C-r>V

    imap <C-z> <Esc>uI
    imap <C-y> <Esc><C-r>I

    " Find and Find/Replace support for normal, visual, and insert mode
    nmap <C-f> :promptfind<CR>
    nmap <C-h> :promptrepl<CR>

    vmap <C-f> <Esc>:promptfind<CR>
    vmap <C-h> <Esc>:promptrepl<CR>

    imap <C-f> <C-o>:promptfind<CR>
    imap <C-h> <C-o>:promptrepl<CR>
endif
    
por 21.03.2016 / 07:03
-1

tl; dr - vnoremap p "_c *

Aqui está uma lista dos meus mapeamentos completos:
"Corrigir cópia / colagem de registro
   nnoremap DD "* dd
   nnoremap D "* d
   vnoremap D " d
   nnoremap d "_d
   nnoremap dd "_dd
   vnoremap d "_d
   nnoremap s "_s
   vnoremap s "_s
   nnoremap c "_c
   vnoremap c "_c
   nnoremap x "_x
   vnoremap x "_x
   vnoremap p "_c

"Cole em nova linha
    nnoremap, p op
    nnoremap, P Op

    
por 18.11.2017 / 00:33