¿Cómo reemplazo-pego el texto arrancado en vim sin tirar de las líneas eliminadas?

39

Por lo general, me encuentro copiando texto de un punto a otro mientras sobrescribo el texto antiguo donde se pega el nuevo:

blah1
newtext
blah2
wrong1
blah3
wrong2
blah4

Supongamos que marco visualmente newtexty lo yanimo. Ahora selecciono wrong1(que podría ser cualquier cosa, no necesariamente solo una palabra) y pasigno el aste newtext. Sin embargo, si ahora hago lo mismo wrong2, será reemplazado con en wrong1lugar de newtext.

Entonces, ¿cómo evito que el texto que está en el búfer se intercambie con el texto que estoy sobrescribiendo actualmente?

Editar 1

Aunque me gustan bastante las sugerencias de registro (creo que comenzaré a usar registros más, ahora que descubrí el :discomando), voy con una modificación de la respuesta de jinfield , porque no uso el modo de intercambio.

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

hace el truco perfectamente

Editar 2

Fui demasiado rápido; La solución de romainl es precisamente lo que estaba buscando, sin el truco en Edición 1 .
En realidad, vnoremap p "_dPes suficiente!
Entonces, cambiando la respuesta aceptada.

máscara de bits
fuente
2
Hola, digo, lo he usado durante mucho tiempo vnoremap p "_dP map, y he notado que no funciona bien para la última palabra / carácter en una línea. He ido a la vuelta vnoremap p "0p, vnoremap P "0Py set clipboard=unnamed(para OSX)
Kache
vnoremap p "_dPelimina el espacio en blanco en la pasta. Edit 1 funciona perfectamente.
Vaclav Kasal

Respuestas:

21

Tengo estas asignaciones en mi .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

"_es el "registro de agujeros negros", de acuerdo con :help "_:

"Al escribir en este registro, no sucede nada. Esto se puede usar para eliminar texto sin afectar los registros normales. Al leer desde este registro, no se devuelve nada. {No en Vi}"

romainl
fuente
1
Lo he usado vnoremap p "_dP mapy noté que no funciona bien para la última palabra / carácter en una línea. He ido a la vuelta vnoremap p "0p, vnoremap P "0Py set clipboard=unnamed(para OSX)
Kache
vnoremap p "_dPdejar de trabajar para mí en el modo de selección, pero vnoremap <leader>p "_dPfunciona
whitesiroi
1
tal vez <leader>es un marcador de posición que se supone que debo reemplazar por algo, pero esto solo funciona para mí si lo elimino. ¿Qué significa aquí?
Hashbrown
1
@Hashbrown, :help mapleader.
romainl
Pequeña advertencia: el vnoremap <leader>pmapeo no funciona correctamente en la última línea del búfer porque tan pronto como elimine esa última línea del búfer, ahora Pestará en la última línea de un segundo y pegará sobre esa línea, en lugar de abajo
Kal
13

Además del búfer estándar, puede extraer texto en búferes con nombre y luego colocarlos en esos búferes con nombre. Hay hasta 26 buffers con nombre que puede usar (uno para cada letra). Use comillas dobles y una letra para acceder a un búfer con nombre. Ejemplos:

"dyy - Yank la línea actual en el búfer d.
"a7yy- Yank las siguientes siete líneas en el búfer a.
"dP- Ponga el contenido del búfer d antes del cursor.
"ap- Ponga el contenido del búfer a después del cursor

Otra cosa interesante, si usa una letra mayúscula en lugar de minúsculas, es decir, "Dyyla línea actual se agregará al búfer d en lugar de reemplazarlo. Más detalles en el libro de O`Reilly: http://docstore.mik.ua/orelly/unix/vi/ch04_03.htm

Tradsud
fuente
3
Muy buena cosa. Conocía los buffers, pero no los relacioné con este problema. Todavía es engorroso para "atodo, pero está bien.
bitmask
4

Cuando se usa puten modo visual, el texto que está reemplazando wrong1se sobrescribe con el contenido del registro 'sin nombre'.

Esto realmente funciona 'poniendo' el registro después de la selección y luego eliminando la selección. El problema es que esta eliminación ahora se almacena en el unnamedregistro y se usará para la próxima putacción.

La solución, según :h v_p, es tirar en un registro con nombre, como "0ypegar usando "0ptantas veces como sea necesario. Puede ser útil mapear <leader>yy <leader>pusar un registro con nombre, si esto es algo que hace con frecuencia.

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

para más ayuda ver:

:help v_p
:help map
Jinfield
fuente
Esta solución parece más útil, hasta que surge algo inteligente del vim mismo.
Yugal Jindle
4

"0Es importante saber cómo pegar desde el registro, pero a menudo desea reemplazarlo muchas veces. Si lo convierte en una acción repetible, puede usar el .operador, como aludió garyjohn. Se explica en la wiki de 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". 
Jerph
fuente
3

Cuando tira del texto al registro sin nombre *, también se coloca una copia en el registro 0. Cada vez que reemplaza el texto seleccionado, puede pegar desde el registro 0. Ver

:help registers

Además, si está reemplazando varias palabras con la misma palabra, simplemente puede pasar al comienzo de la palabra que desea reemplazar y escribir .. Eso repetirá la última operación de edición. Ver

:help single-repeat

* Las ubicaciones de almacenamiento en las que tira y coloca se denominan registros. Un búfer es lo que edita, generalmente una copia de un archivo del disco.

garyjohn
fuente
1

Necesito esto tan a menudo, escribí un complemento para eso: Reemplazar con registro .

Este complemento ofrece un grcomando dos en uno que reemplaza el texto cubierto por un {movimiento}, línea (s) completa (s) o la selección actual con el contenido de un registro; el texto antiguo se elimina en el registro de agujeros negros, es decir, se ha ido.

Ingo Karkat
fuente
1

Como algo como vnoremap p "_dP(también probé xo c) tiene problemas con el inicio y el final de la línea, terminé haciendo esto: vnoremap p :<C-U>let @p = @+<CR>gvp:let @+ = @p<CR>lo que encontré más simple que los complementos existentes (que tampoco funcionaba set clipboard=unnamedplusde fábrica). Entonces, lo que hace es:

  • cambiar al modo de comando
  • eliminar rango ( C-U)
  • +registro de respaldo (debido a unnamed plus, las alternativas son "y *dependiendo de su configuración) parap
  • recuperar selección y pegar
  • cambiar al modo comando nuevamente
  • recuperar registro
Sebastian Blask
fuente
¡Perfecto! Esta es la primera de estas opciones que funcionó exactamente como se esperaba para mí. ¡Gracias!
Jamis Charles
1

Esto es lo que uso (literalmente copiado de mi .vimrc) para el estilo de Windows Control + X cortar / Control + C copiar / Control + V pegar / Control + S guardar / Control + F buscar / Control + H reemplazar el comportamiento.

La función smartpaste () debe contener lo que busca, es decir, una forma de pegar sobre el texto resaltado sin tirar simultáneamente de lo seleccionado.

" Windows common keyboard shortcuts and pasting behavior {{{

" Uncomment to enable debugging.
" Check debug output with :messages
let s:debug_smart_cut = 0
let s:debug_smart_copy = 0
let s:debug_smart_paste = 0

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

    if exists("s:debug_smart_cut") && s:debug_smart_cut
        echomsg "SmartCut '+' buffer: " . @+
    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

    if exists("s:debug_smart_copy") && s:debug_smart_copy
        echomsg "SmartCopy '+' buffer: " . @+
    endif
endfunction

" Delete to black hole register before pasting. This function is a smarter version of "_d"+P or "_dp to handle special cases better.
" SOURCE: http://stackoverflow.com/questions/12625722/vim-toggling-buffer-overwrite-behavior-when-deleting
function! SmartPaste()
    let mode = 'gv'

    let delete = '"_d'

    let reg = '"+'

    " See :help '> for more information. Hint: if you select some text and press ':' you will see :'<,'>
    " SOURCE: http://superuser.com/questions/723621/how-can-i-check-if-the-cursor-is-at-the-end-of-a-line
    " SOURCE: http://stackoverflow.com/questions/7262536/vim-count-lines-in-selected-range
    " SOURCE: https://git.zug.fr/config/vim/blob/master/init.vim
    " SOURCE: https://git.zug.fr/config/vim/blob/master/after/plugin/zzzmappings.vim
    let currentColumn = col(".")
    let currentLine = line(".")
    let lastVisibleLetterColumn = col("$") - 1
    let lastLineOfBuffer = line("$")
    let selectionEndLine = line("'>")
    let selectionEndLineLength = len(getline(selectionEndLine))
    let nextLineLength = len(getline(currentLine + 1))
    let selectionStartColumn = col("'<")
    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 exists("s:debug_smart_paste") && s:debug_smart_paste
            echomsg "SmartPaste special case #1"
        endif

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

        if exists("s:debug_smart_paste") && s:debug_smart_paste
            echomsg "SmartPaste special case #2"
        endif

    " 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 exists("s:debug_smart_paste") && s:debug_smart_paste
            echomsg "SmartPaste special case #3"
        endif

    " 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
        " SOURCE:  http://vim.wikia.com/wiki/Quickly_adding_and_deleting_empty_lines

        " Fixes bug where if the last line is fully selected (Shift + V) and a paste occurs, that the paste appears to insert after the first character of the line above it because the delete operation [which occurs before the paste]
        " is causing the caret to go up a line, and then 'p' cmd causes the paste to occur after the caret, thereby pasting after the first letter of that line.
        " However this but does not occur if there's a blank line underneath the selected line, prior to deleting it, as the cursor goes down after the delete in that situation.
        call append(selectionEndLine, "")

        let cmd = 'p'

        if exists("s:debug_smart_paste") && s:debug_smart_paste
            echomsg "SmartPaste special case #4"
        endif

    else
        let cmd = 'p'

        if exists("s:debug_smart_paste") && s:debug_smart_paste
            echomsg "SmartPaste default case"
        endif
    endif

    if exists("s:debug_smart_paste") && s:debug_smart_paste
        echomsg "SmartPaste debug info:"
        echomsg "    currentColumn: " . currentColumn
        echomsg "    currentLine: " . currentLine
        echomsg "    lastVisibleLetterColumn: " . lastVisibleLetterColumn
        echomsg "    lastLineOfBuffer: " . lastLineOfBuffer
        echomsg "    selectionEndLine: " . selectionEndLine
        echomsg "    selectionEndLineLength: " . selectionEndLineLength
        echomsg "    nextLineLength: " . nextLineLength
        echomsg "    selectionStartColumn: " . selectionStartColumn
        echomsg "    selectionEndColumn: " . selectionEndColumn
        echomsg "    cmd: " . cmd
        echo [getpos("'<")[1:2], getpos("'>")[1:2]]
        echo "visualmode(): " . visualmode()
        echo "mode(): " . mode()
    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

" p or P delete to black hole register before pasting
" NOTE: <C-u> removes the '<,'> visual-selection from the command line. See :h c_CTRL-u
vnoremap <silent> p :<C-u>call SmartPaste()<CR>
vnoremap <silent> P :<C-u>call SmartPaste()<CR>

" MiddleMouse delete to black hole register before pasting
nnoremap <MiddleMouse> "+p " Changes default behavior from 'P' mode to 'p' mode for normal mode middle-mouse pasting
" NOTE: <C-u> removes the '<,'> visual-selection from the command line. See :h c_CTRL-u
vnoremap <silent> <MiddleMouse> :<C-u>call SmartPaste()<CR>
inoremap <MiddleMouse> <C-r><C-o>+

" Disable weird multi-click things you can do with middle mouse button
" SOURCE: http://vim.wikia.com/wiki/Mouse_wheel_for_scroll_only_-_disable_middle_button_paste
noremap <2-MiddleMouse> <Nop>
inoremap <2-MiddleMouse> <Nop>
noremap <3-MiddleMouse> <Nop>
inoremap <3-MiddleMouse> <Nop>
noremap <4-MiddleMouse> <Nop>
inoremap <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
    " SOURCE: https://opensource.apple.com/source/vim/vim-62.41.2/runtime/macmap.vim.auto.html
    " NOTE: Only copy and paste are possible in the command line from what i can tell.
    "       Their is no undo for text typed in the command line and you cannot paste text onto a selection of text to replace it.
    cnoremap <C-c> <C-y>
    cnoremap <C-v> <C-r>+
    " TODO: Is their a select-all for the command line???

    " Cut, copy, and paste support for visual and insert mode (not for normal mode)
    " SOURCE: http://superuser.com/questions/10588/how-to-make-cut-copy-paste-in-gvim-on-ubuntu-work-with-ctrlx-ctrlc-ctrlv
    " NOTE: <C-u> removes the '<,'> visual-selection from the command line. See :h c_CTRL-u
    vnoremap <silent> <C-x> :<C-u>call SmartCut()<CR>
    vnoremap <silent> <C-c> :<C-u>call SmartCopy()<CR>
    vnoremap <silent> <C-v> :<C-u>call SmartPaste()<CR>
    inoremap <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
    nnoremap <C-a> ggVG
    vnoremap <C-a> ggVG
    inoremap <C-a> <Esc>ggVG

    " Save file support for normal, visual, and insert mode
    " SOURCE: http://vim.wikia.com/wiki/Map_Ctrl-S_to_save_current_or_new_files
    " 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
    nnoremap <silent> <C-s> :update<CR>
    " NOTE: <C-u> removes the '<,'> visual-selection from the command line. See :h c_CTRL-u
    vnoremap <silent> <C-s> :<C-u>update<CR>V
    " NOTE: <C-o> executes a normal-mode command without leaving insert mode. See :help ins-special-special
    "inoremap <silent> <C-s> <C-o>:update<CR>
    "
    " <C-o> doesn't seem to work while also using the "Open the OmniCompletion menu as you type" code while the menu is visible.
    " Doing "call feedkeys("\<C-x>\<C-o>", "n")" to perform omni completion seems to be the issue.
    " However doing "call feedkeys("\<C-x>\<C-i>", "n")" to perform keywork completion seems to work without issue.
    "
    " Workaround will exit insert mode to execute the command and then enter insert mode.
    inoremap <silent> <C-s> <Esc>:update<CR>I

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

    " NOTE: <C-u> removes the '<,'> visual-selection from the command line. See :h c_CTRL-u
    vnoremap <C-z> :<C-u>uV
    vnoremap <C-y> :<C-u><C-r>V

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

    function! Find()
        let wordUnderCursor = expand('<cword>')
        if len(wordUnderCursor) > 0
            execute 'promptfind ' . wordUnderCursor
        else
            execute 'promptfind'
        endif
    endfunction

    function! Replace()
        let wordUnderCursor = expand('<cword>')
        if len(wordUnderCursor) > 0
            execute 'promptrepl ' . wordUnderCursor
        else
            execute 'promptrepl'
        endif
    endfunction

    " Find and Find/Replace support for normal, visual, and insert mode
    nnoremap <C-f> :call Find()<CR>
    nnoremap <C-h> :call Replace()<CR>

    " NOTE: <C-u> removes the '<,'> visual-selection from the command line. See :h c_CTRL-u
    vnoremap <C-f> :<C-u>call Find()<CR>
    vnoremap <C-h> :<C-u>call Replace()<CR>

    " NOTE: <C-o> executes a normal-mode command without leaving insert mode. See :help ins-special-special
    inoremap <C-f> <C-o>:call Find()<CR>
    inoremap <C-h> <C-o>:call Replace()<CR>
endif

" }}} Windows common keyboard shortcuts and pasting behavior
EnfocadoLobo
fuente
-1

tl; dr - vnoremap p "_c *

Aquí hay una lista de mis asignaciones completas:
"Reparar registro copiar / pegar
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

"Pegar en nueva línea
nnoremap, p op
nnoremap, P Op

kawerte
fuente