Как заменить вставленный текст в vim, не удаляя удаленные строки?

Поэтому я обычно копирую текст из одной точки в другую, перезаписывая старый текст, куда вставляется новый:

blah1
newtext
blah2
wrong1
blah3
wrong2
blah4

Предположим, я визуальный знак newtext а также yАнк это. Теперь я выбираю wrong1 (который может быть чем угодно, не обязательно просто словом) и pAste newtext, Однако, если я сейчас сделаю то же самое с wrong2 это будет заменено на wrong1 вместо newtext,

Итак, как я могу предотвратить замену текста, который находится в буфере, текстом, который я сейчас перезаписываю?

Редактировать 1

Хотя мне очень нравятся предложения по регистрации (я думаю, что я начну использовать регистры больше, теперь, когда я обнаружил :dis команда), я иду с модификацией ответа Джинфилда, потому что я не использую режим обмена.

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

делает трюк отлично.

Редактировать 2

Я был слишком быстр; Решение romainl- это именно то, что я искал, без взлома в Edit 1.
На самом деле, vnoremap p "_dP достаточно!
Итак, меняем принятый ответ.

13 ответов

Решение

У меня есть эти сопоставления в моем.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

"_ это "регистр черной дыры", согласно :help "_:

"При записи в этот регистр ничего не происходит. Это можно использовать для удаления текста, не затрагивая обычные регистры. При чтении из этого регистра ничего не возвращается. {Не в Vi}"

В дополнение к стандартному буферу вы можете вытянуть текст в именованные буферы, а затем поместить из этих именованных буферов. Вы можете использовать до 26 именованных буферов (по одному на каждую букву). Используйте двойные кавычки и букву для доступа к названному буферу. Примеры:

"dyy - Снять текущую строку в буфер d.
"a7yy - Снять следующие семь строк в буфер a.
"dP - Поместите содержимое буфера d перед курсором.
"ap - Поместить содержимое буфера после курсора

Еще одна крутая вещь, если вы используете заглавную букву вместо строчных, т.е. "Dyy текущая строка будет добавлена ​​в буфер d вместо ее замены. Подробнее в книге О`Рейли: http://docstore.mik.ua/orelly/unix/vi/ch04_03.htm

Когда используешь put в визуальном режиме текст, который вы заменяете, wrong1, перезаписывается содержимым "unamed" регистра.

Это на самом деле работает, "помещая" регистр после выбора, а затем удаляя выбор. Проблема в том, что это удаление теперь хранится в unnamed зарегистрироваться и будет использоваться для следующего put действие.

Решение, согласно :h v_p, чтобы вставить в именованный регистр, такой как "0yзатем вставьте, используя "0p столько времени, сколько вам нужно. Это может быть полезно для карты <leader>y а также <leader>p использовать именованный регистр, если вы часто это делаете.

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

для получения дополнительной помощи см.:

:help v_p
:help map

ИспользоватьPвставить, не дергая удаленный текст.

:помогите v_P

С помощью P безымянный регистр не изменяется (и ни выделение, ни буфер обмена), вы можете повторить то же изменение.

Такое поведение было введено в версии 8.2.4242 (28 января 2022 г.) и уточнено в версии 8.2.4881 (06 мая 2022 г.).

Или если у вас слишком сильная мышечная память:

      xnoremap p P

Вставка из "0 зарегистрироваться важно знать, но вы часто хотите заменить много раз. Если вы делаете это повторяемое действие, вы можете использовать . оператор, на что ссылается Гариджон. Это объясняется на вики-сайте 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". 

Когда вы вставляете текст в безымянный регистр *, копия также помещается в регистр 0. Каждый раз, когда вы заменяете выделенный текст, вы можете просто вставить из регистра 0. Увидеть

:help registers

Кроме того, если вы заменяете несколько слов одним и тем же словом, вы можете просто перейти к началу слова, которое нужно заменить, и набрать ., Это будет повторять последнюю операцию редактирования. Увидеть

:help single-repeat

* Места хранения, в которые вы вставляете и кладете, называются регистрами. Буфер - это то, что вы редактируете, обычно это копия файла с диска.

Я использую clipboard=unamedplus поэтому я обнаружил, что многие решения здесь не работают, потому что паста помещала перезаписанный текст в "+ вместо "". Я также обнаружил, что "_dP были проблемы в конце строк.

Однако я обнаружил, что с помощью c работал.

set clipboard=unnamedplus " Use system clipboard.

" Don't put pasted-over content into the clipboard.
vnoremap p "_c<C-r><C-o>+<Esc>

Это в основном c изменяет текст и использует вставку режима вставки (<C-r><C-o>+) безымянного реестра. Поскольку курсор режима вставки может быть после последнего символа строки, это не проблема в конце строк.

Возможные хитрости:

  • Если вы не хотите отменять обычный p команда просто используйте <Leader>p.
  • Если вы используете другой регистр клибборда, замените + с участием " или же *.

Выделите текст и вставьте егоP(верхний регистр).

Пример:

      viwP

Видетьh: v_Pдля получения дополнительной информации.

Как-то вроде vnoremap p "_dP(Я тоже пробовал x или же c) есть проблемы с началом и концом строки, в итоге я сделал это: vnoremap p :<C-U>let @p = @+<CR>gvp:let @+ = @p<CR>который я нашел проще, чем существующие плагины (которые также не работали с set clipboard=unnamedplus из коробки). Итак, что это делает:

  • переключиться в командный режим
  • удалить диапазон (C-U)
  • резервное копирование + зарегистрироваться (из-за неназванного плюса, альтернативы " а также * в зависимости от вашей конфигурации) p
  • восстановить выделение и вставить
  • снова переключиться в командный режим
  • восстановить регистр

Мне нужно это так часто, я написал для этого плагин: ReplaceWithRegister.

Этот плагин предлагает два в одном gr команда, которая заменяет текст, охватываемый {motion}, всей строкой (ами) или текущим выделением, содержимым регистра; старый текст удаляется в регистр черной дыры, т.е.

Это то, что я использую для поведения вставки Windows, которое позволяет мне визуально выбирать текст и вставлять содержимое буфера обмена, чтобы перезаписать то, что было выбрано, без повреждения содержимого буфера обмена в процессе.

Примечание. Код, представленный здесь, сокращен. Полный список с возможностью отладки, а также другие комментарии и отзывы см.: http://pastebin.com/aBEsm5mV

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

Использование:

" 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

Во многих случаях может работать следующее: c+CtrlR+0+Esc.
Вам может понадобиться сделать

:set paste

прежде, чем подавить аутоиндент.

tl;dr - vnoremap p "_c*

Вот список моих полных сопоставлений:
"Исправление копирования / вставки в регистр
nnoremap DD "*dd
без карты D "* d
Внокарта Д " Д
нет карты d "_d
nnoremap dd "_dd
vnoremap d "_d
nnoremap s "_s
vnoremap s "_s
без карты c "_c
vnoremap c "_c
nnoremap x "_x
vnoremap x "_x
vnoremap p "_c

"Вставить на новую строку
nnoremap,p op
без карты,P Op

Другие вопросы по тегам