Come posso sostituire-incollare il testo strappato in VIM senza strappare le righe cancellate?


39

Quindi di solito mi ritrovo a copiare il testo da un punto all'altro mentre sovrascrivo il vecchio testo dove viene incollato il nuovo:

blah1
newtext
blah2
wrong1
blah3
wrong2
blah4

Supponiamo che io visualizzi il segno newtexte lo yank. Ora seleziono wrong1(che potrebbe essere qualsiasi cosa, non necessariamente solo una parola) e pinserisco il newtext. Tuttavia, se ora faccio lo stesso con wrong2esso sarà sostituito con wrong1al posto di newtext.

Quindi, come posso evitare che il testo nel buffer venga scambiato con il testo che sto sovrascrivendo?

Modifica 1

Anche se mi piacciono abbastanza i suggerimenti di reigister (penso che inizierò ad usare di più i registri, ora che ho scoperto il :discomando), vado con una modifica della risposta di jinfield , perché non uso la modalità di scambio.

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

fa il trucco perfettamente.

Modifica 2

Ero troppo veloce; La soluzione di Romainl è esattamente quello che stavo cercando, senza l'hacking in Edit 1 .
In realtà, vnoremap p "_dPè abbastanza!
Quindi, cambiando risposta accettata.


2
Ehi amico, l'ho usato a lungo vnoremap p "_dP map, e ho notato che non funziona bene per l'ultima parola / carattere in una riga. Ho di nuovo andato al vnoremap p "0p, vnoremap P "0Pe set clipboard=unnamed(per OSX)
Kache

vnoremap p "_dPrimuove gli spazi bianchi sulla pasta. Modifica 1 funziona perfettamente.
Vaclav Kasal,

Risposte:


21

Ho queste mappature nel mio .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

"_è il "registro del buco nero", secondo :help "_:

"Quando si scrive in questo registro, non succede nulla. Questo può essere usato per cancellare il testo senza influenzare i normali registri. Quando si legge da questo registro, non viene restituito nulla. {Not in Vi}"


1
L'ho usato vnoremap p "_dP mape ho notato che non funziona bene per l'ultima parola / carattere in una riga. Ho di nuovo andato al vnoremap p "0p, vnoremap P "0Pe set clipboard=unnamed(per OSX)
Kache

vnoremap p "_dPsmetti di lavorare per me in modalità di selezione, ma vnoremap <leader>p "_dPfunziona
whitesiroi il

1
forse <leader>è un segnaposto che dovrei sapere per sostituire qualcosa, ma questo ha funzionato solo per me se l'ho rimosso. Cosa significa qui?
Hashbrown,

1
@Hashbrown, :help mapleader.
romainl

Piccolo avvertimento: la vnoremap <leader>pmappatura non funziona correttamente sull'ultima riga del buffer perché non appena si elimina l'ultima riga del buffer, ci si trova ora sull'ultima riga dell'ultima riga e Pincollerà sopra quella riga, invece di sotto.
Kal,

13

Oltre al buffer standard, è possibile trascinare il testo nei buffer con nome e quindi inserirli da tali buffer. Esistono fino a 26 buffer con nome che è possibile utilizzare (uno per ogni lettera). Utilizzare virgolette doppie e una lettera per accedere a un buffer con nome. Esempi:

"dyy - Trascina la linea corrente nel buffer d.
"a7yy- Yank successive sette righe nel buffer a.
"dP- Inserisci il contenuto del buffer d prima del cursore.
"ap- Posiziona il contenuto del buffer dopo il cursore

Un'altra cosa interessante, se si utilizza una lettera maiuscola anziché minuscola, ovvero "Dyyla riga corrente verrà aggiunta al buffer d invece di sostituirla. Maggiori dettagli nel libro di O`Reilly: http://docstore.mik.ua/orelly/unix/vi/ch04_03.htm


3
Cosa molto bella. Conoscevo i buffer, ma non li collegavo a questo problema. È ancora ingombrante per "atutto, ma va bene.
Maschera di bit

4

Quando si utilizza putin modalità visiva, il testo che si sta sostituendo wrong1viene sovrascritto dal contenuto del registro "senza nome".

In realtà funziona "inserendo" il registro dopo la selezione e quindi eliminando la selezione. Il problema è che questa eliminazione è ora memorizzata nel unnamedregistro e verrà utilizzata per l' putazione successiva .

La soluzione, secondo :h v_p, è quella di fare uno yank in un registro con nome, ad esempio "0y, quindi incollarlo usando "0ptutte le volte che è necessario. Può essere utile mappare <leader>ye <leader>putilizzare un registro con nome, se questo è qualcosa che fai di frequente.

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

per ulteriori informazioni, consultare:

:help v_p
:help map

Questa soluzione sembra più utilizzabile, fino a quando qualcosa di intelligente non emerge dalla stessa vim.
Yugal Jindle

4

Incollare dal "0registro è importante da sapere, ma spesso si desidera sostituire più volte. Se lo rendi un'azione ripetibile, puoi utilizzare l' .operatore, come indicato da Garyjohn. È spiegato sul wiki di 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". 

3

Quando si trascina il testo nel registro senza nome *, anche una copia viene inserita nel registro 0. Ogni volta che si sostituisce il testo selezionato, è possibile incollare dal registro 0. Vedere

:help registers

Inoltre, se stai sostituendo un numero di parole con la stessa parola, puoi semplicemente spostarti all'inizio della parola da sostituire e digitare .. Ciò ripeterà l'ultima operazione di modifica. Vedere

:help single-repeat

* Le posizioni di archiviazione in cui si esegue il tiro e il cui inserimento vengono denominate registri. Un buffer è la cosa che si modifica, di solito una copia di un file dal disco.


1

Ne ho bisogno così spesso, ho scritto un plugin per quello: ReplaceWithRegister .

Questo plugin offre un grcomando due in uno che sostituisce il testo coperto da un {motion}, intere righe o la selezione corrente con il contenuto di un registro; il vecchio testo viene cancellato nel registro del buco nero, cioè è sparito.


1

Dato che qualcosa come vnoremap p "_dP(ho anche provato xo c) ha problemi con l'inizio e la fine della linea, ho finito per farlo: vnoremap p :<C-U>let @p = @+<CR>gvp:let @+ = @p<CR>cosa che ho trovato più semplice rispetto ai plugin esistenti (che non funzionavano anche con set clipboard=unnamedplusla confezione). Quindi quello che fa è:

  • passa alla modalità di comando
  • rimuovi intervallo ( C-U)
  • +registro di backup (a causa di unnamedplus, le alternative sono "e in *base alla configurazione) ap
  • recupera la selezione e incolla
  • passa nuovamente alla modalità di comando
  • registro di recupero

Perfezionare! Questa è la prima di queste opzioni che ha funzionato esattamente come mi aspettavo. Grazie!
Jamis Charles,

1

Questo è quello che uso (letteralmente copiato dal mio .vimrc) per Control in stile Windows + X cut / Control + C copy / Control + V paste / Control + S save / Control + F find / Control + H per il comportamento di sostituzione.

La funzione smartpaste () dovrebbe contenere ciò che cerchi, ovvero un modo per incollare il testo evidenziato senza strappare contemporaneamente ciò che è stato selezionato.

" 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

-1

tl; dr - vnoremap p "_c *

Ecco un elenco delle mie mappature complete:
"Correggi copia / incolla del
registro nnoremap DD" * dd
nnoremap D "* d
vnoremap D" d
nnnoremap 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

"Incolla su nuova riga
nnoremap, p op
nnoremap, P op

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.