Wie ersetze ich das Einfügen von Text mit Ruckeln in vim, ohne die gelöschten Zeilen zu ruckeln?

39

Normalerweise kopiere ich Text von einem Punkt zum anderen, während ich alten Text überschreibe, in den der neue eingefügt wird:

blah1
newtext
blah2
wrong1
blah3
wrong2
blah4

Angenommen, ich markiere es visuell newtextund yknicke es an. Jetzt wähle ich wrong1(das könnte alles sein, nicht unbedingt nur ein Wort) und paste die newtext. Allerdings, wenn ich jetzt das gleiche mit tue wrong2es mit Fassung wrong1statt newtext.

Wie verhindere ich, dass der Text im Puffer mit dem Text ausgetauscht wird, den ich gerade überschreibe?

Bearbeiten 1

Obwohl mir die Vorschläge für den Austausch von Registern sehr gefallen (ich glaube, ich werde mit der Verwendung von Registern anfangen, nachdem ich den :disBefehl entdeckt habe), werde ich eine Modifikation der Antwort von jinfield vornehmen , da ich den Austauschmodus nicht verwende.

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

macht den Trick perfekt.

Bearbeiten 2

Ich war zu schnell; romainls lösung ist genau das, wonach ich gesucht habe, ohne den hack in edit 1 .
Eigentlich vnoremap p "_dPreicht das!
Also, akzeptierte Antwort ändern.

Bitmaske
quelle
2
Hey, ich habe das schon lange benutzt vnoremap p "_dP mapund festgestellt, dass es für das letzte Wort / Zeichen in einer Zeile nicht gut funktioniert. Ich bin gegangen , zurück in das vnoremap p "0p, vnoremap P "0Pund set clipboard=unnamed(für OSX)
Kache
vnoremap p "_dPEntfernt Leerstellen auf der Paste. Edit 1 funktioniert einwandfrei.
Vaclav Kasal,

Antworten:

21

Ich habe diese Zuordnungen in meinem .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

"_ist das "Blackhole Register" nach :help "_:

"Beim Schreiben in dieses Register passiert nichts. Dies kann verwendet werden, um Text zu löschen, ohne die normalen Register zu beeinflussen. Beim Lesen aus diesem Register wird nichts zurückgegeben. {Not in Vi}"

romainl
quelle
1
Ich habe das benutzt vnoremap p "_dP mapund festgestellt, dass es für das letzte Wort / Zeichen in einer Zeile nicht gut funktioniert. Ich bin gegangen , zurück in das vnoremap p "0p, vnoremap P "0Pund set clipboard=unnamed(für OSX)
Kache
vnoremap p "_dPvnoremap <leader>p "_dP
Hör auf
1
Vielleicht <leader>ist es ein Platzhalter, den ich durch etwas ersetzen soll, aber das hat nur bei mir funktioniert, wenn ich es entfernt habe. Was heißt das hier?
Hashbrown
1
@Hashbrown, :help mapleader.
Romainl
Kleine Einschränkung: die vnoremap <leader>pZuordnung nicht korrekt , weil so schnell in der letzten Zeile des Puffers funktioniert , wie Sie die letzte Zeile des Puffers löschen, Sie sind jetzt auf der einst zweitletzte Zeile, und das Poberhalb dieser Linie einfügen, statt unten.
Kal
13

Zusätzlich zum Standardpuffer können Sie Text in benannte Puffer ziehen und dann aus diesen benannten Puffern einfügen. Sie können bis zu 26 benannte Puffer verwenden (einen für jeden Buchstaben). Verwenden Sie doppelte Anführungszeichen und einen Buchstaben, um auf einen benannten Puffer zuzugreifen. Beispiele:

"dyy - Aktuelle Zeile in Puffer d ziehen.
"a7yy- Ziehen Sie die nächsten sieben Zeilen in den Puffer a.
"dP- Setzen Sie den Inhalt des Puffers d vor den Cursor.
"ap- Setzen Sie den Inhalt des Puffers a hinter den Cursor

Eine andere coole Sache, wenn Sie einen Großbuchstaben anstelle von Kleinbuchstaben verwenden, dh "Dyydie aktuelle Zeile wird an den Puffer d angehängt, anstatt ihn zu ersetzen. Weitere Details im O`Reilly-Buch: http://docstore.mik.ua/orelly/unix/vi/ch04_03.htm

Tradsud
quelle
3
Sehr coole Sache. Ich wusste von Puffern, habe sie aber nicht mit diesem Problem in Verbindung gebracht. Es ist immer noch umständlich für "aalles, aber okay.
Bitmaske
4

Bei Verwendung putim visuellen Modus wird der zu ersetzende Text wrong1durch den Inhalt des Registers "unamed" überschrieben.

Dies funktioniert tatsächlich, indem das Register nach der Auswahl 'abgelegt' und dann die Auswahl gelöscht wird. Das Problem ist, dass diese Löschung jetzt im unnamedRegister gespeichert wird und für die nächste putAktion verwendet wird.

Die Lösung besteht laut darin :h v_p, in ein benanntes Register zu ziehen, z. B. "0yund dann "0pso viel Zeit wie nötig einzufügen . Es kann hilfreich sein, ein benanntes Register zuzuordnen <leader>yund <leader>pzu verwenden, wenn Sie dies häufig tun.

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

Weitere Hilfe finden Sie unter:

:help v_p
:help map
Jinfield
quelle
Diese Lösung scheint am nützlichsten zu sein, bis etwas Kluges aus dem Vim selbst hervorgeht.
Yugal Jindle,
4

Das Einfügen aus dem "0Register ist wichtig zu wissen, aber Sie möchten oft viele Male ersetzen. Wenn Sie es zu einer wiederholbaren Aktion machen, können Sie den .Operator verwenden, auf den garyjohn anspielt. Es wird im Vim-Wiki erklärt :

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
quelle
3

Wenn Sie den Text in das unbenannte Register * ziehen, wird auch eine Kopie in Register 0 abgelegt. Jedes Mal, wenn Sie den ausgewählten Text ersetzen, können Sie ihn einfach aus dem Register 0 einfügen. Sehen

:help registers

Wenn Sie eine Reihe von Wörtern durch dasselbe Wort ersetzen, können Sie einfach zum Anfang des zu ersetzenden Wortes gehen und es eingeben .. Dadurch wird der letzte Bearbeitungsvorgang wiederholt. Sehen

:help single-repeat

* Die Speicherorte, an die Sie ziehen und aus denen Sie ziehen, werden als Register bezeichnet. Ein Puffer ist das, was Sie bearbeiten, normalerweise eine Kopie einer Datei von der Festplatte.

garyjohn
quelle
1

Ich brauche das so oft, ich habe ein Plugin dafür geschrieben: ReplaceWithRegister .

Dieses Plugin bietet einen Zwei-in-Eins- grBefehl, der Text, der durch eine {Bewegung}, eine ganze Zeile oder die aktuelle Auswahl abgedeckt ist, durch den Inhalt eines Registers ersetzt. Der alte Text wird im Black-Hole-Register gelöscht, dh er ist weg.

Ingo Karkat
quelle
1

Da etwas wie vnoremap p "_dP(ich habe es auch versucht xoder versucht c) Probleme mit dem Zeilenanfang und -ende hat, habe ich dies getan: vnoremap p :<C-U>let @p = @+<CR>gvp:let @+ = @p<CR>was ich einfacher fand als die vorhandenen Plugins (die auch nicht ohne weiteres funktionierten set clipboard=unnamedplus). Also, was es tut, ist:

  • in den Befehlsmodus wechseln
  • Bereich entfernen ( C-U)
  • Sicherungsregister +(aufgrund von unnamedplus, Alternativen sind "und *je nach Konfiguration) zup
  • Auswahl wiederherstellen und einfügen
  • Wechseln Sie wieder in den Befehlsmodus
  • Register wiederherstellen
Sebastian Blask
quelle
Perfekt! Dies ist die erste dieser Optionen, die für mich genau wie erwartet funktioniert hat. Vielen Dank!
Jamis Charles
1

Dies ist, was ich benutze (wörtlich aus meiner .vimrc kopiert) für Windows-Stil Control + X Ausschneiden / Control + C Kopieren / Control + V Einfügen / Control + S Speichern / Control + F Suchen / Control + H Ersetzen Verhalten.

Die Funktion smartpaste () sollte das enthalten, wonach Sie suchen, dh eine Möglichkeit, markierten Text einzufügen, ohne gleichzeitig an der ausgewählten Stelle zu ziehen.

" 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
Fokussierter Wolf
quelle
-1

tl; dr - vnoremap p "_c *

Hier ist eine Liste meiner vollständigen Zuordnungen:
"Register kopieren /
einfügen 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


Msgstr "Einfügen in neue Zeile" nnoremap "," p op
nnoremap "," P op "

kawerte
quelle