Comment puis-je remplacer-coller du texte retiré dans vim sans tirer les lignes supprimées?

39

Je me retrouve donc généralement à copier du texte d'un point à un autre tout en écrasant l'ancien texte où le nouveau est collé:

blah1
newtext
blah2
wrong1
blah3
wrong2
blah4

Supposons que je marque visuellement newtextet que je ym'ancre. Maintenant, je sélectionne wrong1(ce qui pourrait être n'importe quoi, pas nécessairement juste un mot) et paste le newtext. Cependant, si je fais maintenant la même chose, wrong2il sera remplacé par wrong1au lieu de newtext.

Alors, comment puis-je empêcher le texte qui se trouve dans le tampon d'être échangé avec le texte que j'écrase actuellement?

Modifier 1

Bien que j'aime bien les suggestions de réenregistrement (je pense que je vais commencer à utiliser plus de registres, maintenant que j'ai découvert la :discommande), je vais avec une modification de la réponse de jinfield , car je n'utilise pas le mode de permutation.

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

fait parfaitement l'affaire.

Modifier 2

J'étais trop rapide; La solution de romainl est exactement ce que je cherchais, sans le hack dans Edit 1 .
En fait, ça vnoremap p "_dPsuffit!
Donc, changer la réponse acceptée.

bitmask
la source
2
Hey fyi, je l'utilise depuis longtemps vnoremap p "_dP mapet j'ai remarqué que cela ne fonctionne pas bien pour le dernier mot / caractère d'une ligne. J'ai de nouveau allé au vnoremap p "0p, vnoremap P "0Pet set clipboard=unnamed(pour Mac OS X)
Kache
vnoremap p "_dPsupprime les espaces blancs sur la pâte. Edit 1 fonctionne parfaitement.
Vaclav Kasal

Réponses:

21

J'ai ces mappages dans mon .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

"_est le "registre des trous noirs", selon :help "_:

"Lors de l'écriture dans ce registre, rien ne se passe. Cela peut être utilisé pour supprimer du texte sans affecter les registres normaux. Lors de la lecture de ce registre, rien n'est retourné. {Absent de Vi}"

romainl
la source
1
J'ai utilisé cela vnoremap p "_dP mapet j'ai remarqué que cela ne fonctionne pas bien pour le dernier mot / caractère d'une ligne. J'ai de nouveau allé au vnoremap p "0p, vnoremap P "0Pet set clipboard=unnamed(pour Mac OS X)
Kache
vnoremap p "_dParrête de travailler pour moi en mode select, mais vnoremap <leader>p "_dPça marche
whitesiroi
1
<leader>est peut - être un espace réservé que je suis censé savoir pour remplacer par quelque chose, mais cela n'a fonctionné pour moi que si je l'ai supprimé. Qu'est-ce que cela signifie ici?
Hashbrown
1
@Hashbrown, :help mapleader.
romainl
Petite mise en garde: le vnoremap <leader>pmappage ne fonctionne pas correctement sur la dernière ligne du tampon car dès que vous supprimez cette dernière ligne du tampon, vous êtes maintenant sur l'avant-dernière ligne, et le Pcollera au-dessus de cette ligne, au lieu de ci-dessous.
Kal
13

En plus du tampon standard, vous pouvez extraire du texte dans des tampons nommés, puis les placer à partir de ces tampons nommés. Vous pouvez utiliser jusqu'à 26 tampons nommés (un pour chaque lettre). Utilisez des guillemets doubles et une lettre pour accéder à un tampon nommé. Exemples:

"dyy - Mettre la ligne courante dans le tampon d.
"a7yy- Récupérez les sept lignes suivantes dans le tampon a.
"dP- Placer le contenu du tampon d avant le curseur.
"ap- Mettre le contenu du tampon un après le curseur

Une autre chose intéressante, si vous utilisez une majuscule au lieu de minuscules, c'est "Dyy-à- dire que la ligne actuelle sera ajoutée au tampon d au lieu de le remplacer. Plus de détails dans le livre O`Reilly: http://docstore.mik.ua/orelly/unix/vi/ch04_03.htm

Tradsud
la source
3
Chose très cool. Je connaissais les tampons, mais je ne les ai pas connectés à ce problème. C'est toujours lourd pour "atout, mais d'accord.
bitmask
4

Lors de l'utilisation puten mode visuel, le texte que vous remplacez wrong1est remplacé par le contenu du registre «sans nom».

Cela fonctionne réellement en «mettant» le registre après la sélection, puis en supprimant la sélection. Le problème est que cette suppression est maintenant stockée dans le unnamedregistre et sera utilisée pour l' putaction suivante .

La solution, selon :h v_p, consiste à extraire dans un registre nommé, tel que "0y, puis à coller en utilisant "0pautant de temps que nécessaire. Il peut être utile de mapper <leader>yet <leader>pd'utiliser un registre nommé, si c'est quelque chose que vous faites fréquemment.

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

pour plus d'aide, voir:

:help v_p
:help map
jinfield
la source
Cette solution semble la plus utilisable, jusqu'à ce que quelque chose d'intelligent surgisse du vim lui-même.
Yugal Jindle
4

Il "0est important de savoir coller à partir du registre, mais vous voulez souvent le remplacer plusieurs fois. Si vous en faites une action répétable, vous pouvez utiliser l' .opérateur, comme mentionné par garyjohn. C'est expliqué sur le wiki 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
la source
3

Lorsque vous tirez le texte dans le registre sans nom *, une copie est également placée dans le registre 0. Chaque fois que vous remplacez le texte sélectionné, vous pouvez simplement coller à partir du registre 0. Voir

:help registers

De plus, si vous remplacez un certain nombre de mots par le même mot, vous pouvez simplement vous déplacer au début du mot à remplacer et taper .. Cela répétera la dernière opération d'édition. Voir

:help single-repeat

* Les emplacements de stockage dans lesquels vous tirez et placez sont appelés registres. Un tampon est la chose que vous modifiez, généralement une copie d'un fichier à partir du disque.

garyjohn
la source
1

J'en ai besoin si souvent, j'ai écrit un plugin pour ça: ReplaceWithRegister .

Ce plugin offre une commande deux en un grqui remplace le texte couvert par un {motion}, une ou des lignes entières ou la sélection actuelle par le contenu d'un registre; l'ancien texte est supprimé dans le registre des trous noirs, c'est-à-dire qu'il a disparu.

Ingo Karkat
la source
1

Comme quelque chose comme vnoremap p "_dP(j'ai également essayé xou c) a des problèmes avec le début et la fin de la ligne, j'ai fini par le faire: vnoremap p :<C-U>let @p = @+<CR>gvp:let @+ = @p<CR>que j'ai trouvé plus simple que les plugins existants (qui ne fonctionnaient pas non plus avec eux set clipboard=unnamedplus). Donc ce que ça fait c'est:

  • passer en mode commande
  • supprimer la plage ( C-U)
  • +registre de sauvegarde (en raison de unlamedplus, les alternatives sont "et *selon votre configuration) pourp
  • récupérer la sélection et coller
  • passer à nouveau en mode commande
  • récupérer le registre
Sebastian Blask
la source
Parfait! C'est la première de ces options qui a fonctionné exactement comme prévu pour moi. Merci!
Jamis Charles
1

C'est ce que j'utilise (littéralement copié de mon .vimrc) pour le contrôle de style Windows + X couper / Contrôle + C copier / Contrôle + V coller / Contrôle + S enregistrer / Contrôle + F trouver / Contrôle + H remplacer le comportement.

La fonction smartpaste () doit contenir ce que vous cherchez, c'est-à-dire un moyen de coller sur du texte en surbrillance sans tirer simultanément ce qui a été sélectionné.

" 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
FocusedWolf
la source
-1

tl; dr - vnoremap p "_c *

Voici une liste de mes mappages complets:
"Corriger l'enregistrement copier / coller
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

"Coller sur une nouvelle ligne
nnoremap, p op
nnoremap, P Op

kawerte
la source