Как мне заменить вставку вырезанного текста в vim без копирования удалённых строк?

Вопрос или проблема

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

blah1
newtext
blah2
wrong1
blah3
wrong2
blah4

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

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

Правка 1

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

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

это работает идеально.

Правка 2

Я был слишком спешным; romainl‘s решение – это именно то, что я искал, без хаков из Правки 1.
На самом деле, vnoremap p "_dP достаточно!
Итак, меняю принятие ответа.

У меня есть следующие привязки в моем .vimrc:

" удаление без копирования
nnoremap <leader>d "_d
vnoremap <leader>d "_d

" заменить текущий выделенный текст на текст по умолчанию
" без копирования
vnoremap <leader>p "_dP

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

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

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

:help v_P

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

Это поведение было введено в v8.2.4242 (2022-01-28) и уточнено в v8.2.4881 (2022-05-06).

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

xnoremap p P

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

"dyy – Копировать текущую строку в буфер d.
"a7yy – Копировать следующие семь строк в буфер a.
"dP – Вставить содержимое буфера d перед курсором.
"ap – Вставить содержимое буфера a после курсора

Еще одна интересная вещь: если вы используете заглавную букву вместо строчной, то есть "Dyy, текущая строка будет добавлена в буфер d, вместо того, чтобы заменять его. Более подробная информация в книге O’Reilly: http://docstore.mik.ua/orelly/unix/vi/ch04_03.htm

При использовании put в визуальном режиме текст, который вы заменяете, wrong1, перезаписывается содержимым ‘неназванного’ регистра.

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

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

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

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

:help v_p
:help map

Вставка из регистра "0 важна для знания, но вы часто хотите заменить много раз. Если вы сделаете это повторяемым действием, вы можете использовать оператор ., как упоминал garyjohn. Это объясняется на вики vim:

yiw     копирует внутреннее слово (копирует слово под курсором, скажем "первое". То же самое, что и выше).
...     Переместите курсор к другому слову (скажем "второе").
ciw<C-r>0   выберите "второе", затем замените его на "первое". Если вы находитесь в начале слова, тогда достаточно cw<C-r>0.
...     Переместите курсор к другому слову (скажем "третье").
.   выберите "третье", затем замените его на "первое". 

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

:help registers

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

:help single-repeat

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

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

Однако я выяснил, что использование c сработало.

set clipboard=unnamedplus " Используйте системный буфер обмена.

" Не помещайте вставленный контент в буфер обмена.
vnoremap p "_c<C-r><C-o>+<Esc>

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

Возможные корректировки:

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

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

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

Выделите текст и вставьте с помощью P (заглавной).

Пример:

viwP

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

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

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

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

:set paste

перед этим, чтобы отключить автоотступ.

Это то, что я использую для поведения вырезания Control + X/копирования Control + C/вставки Control + V/сохранения Control + S/поиска Control + F/замены Control + H в стиле Windows.

Функция SmartPaste() должна содержать то, что вы ищете, т.е. способ вставки поверх выделенного текста без одновременного копирования выбранного.

" Общие сочетания клавиш Windows и поведение вставки {{{

" Рекомендуемые настройки vimrc:
"     Установите буфер обмена так:
"         ЗАМЕТКА: Используйте ^=, чтобы добавить значение к списку, разделенному запятыми. См. :h set^=
"         set clipboard^=unnamedplus            " Работает в Linux, но есть проблемы с копированием в Windows.
"         set clipboard^=unnamed,unnamedplus    " Работает в Linux и Windows (а, вероятно, MacVim, который нуждался в неназванном опции в последний раз, когда я использовал его).
"
"     Установите мышь так:
"         set mouse=a    " Гарантирует, что бинды мыши работают во всех режимах.
"
"     Отключите автоматический выбор:
"         ЗАМЕТКА: Это заставляет щелчки средней мыши в других программах вставлять содержимое буфера Vim's "+ неназванный регистр вместо "* регистра выбранного текста. См. :h go-a
"         set guioptions-=a
"         set guioptions-=A

" Функции {{{

" Раскомментируйте, чтобы включить отладку.
" Проверьте вывод отладки с :messages
" let s:debug_smart_cut = 1
" let s:debug_smart_copy = 1
" let s:debug_smart_paste = 1

function! SmartCut() " {{{
    if !has('clipboard')
        echoerr 'Поддержка буфера обмена требуется для использования этой функции.'
        return
    endif

    let clipboard_register="+"

    " Восстановите визуальное выделение с 'gv' и удалите выделение в буфер обмена.
    " ЗАМЕТКА: 'd' (удаление) лучше, чем 'c' (копирование), потому что он перемещает каретку вправо.
    execute 'normal! gv"' . clipboard_register . 'd'

    " Войти в режим вставки.
    startinsert

    " Получает значение, если оно существует, в противном случае возвращает 0.
    if get(s:, 'debug_smart_cut')
        echomsg "SmartCut"
        echomsg "    содержимое буфера: " . getreg(clipboard_register)
    endif
endfunction " }}}

function! SmartCopy() " {{{
    if !has('clipboard')
        echoerr 'Поддержка буфера обмена требуется для использования этой функции.'
        return
    endif

    let clipboard_register="+"

    " Восстановите визуальное выделение с 'gv' и копируйте выделение в буфер обмена.
    execute 'normal! gv"' . clipboard_register . 'y'

    " Получает значение, если оно существует, в противном случае возвращает 0.
    if get(s:, 'debug_smart_copy')
        echomsg "SmartCopy"
        echomsg "    содержимое буфера: " . getreg(clipboard_register)
    endif
endfunction " }}}

function! SmartPaste() " {{{
    if !has('clipboard')
        echoerr 'Поддержка буфера обмена требуется для использования этой функции.'
        return
    endif

    if !&modifiable
        return
    endif

    " См. :help '> для получения дополнительной информации. Подсказка: если вы выделите текст и нажмёте ':' вы увидите :'<,'>
    " ИСТОЧНИК: http://superuser.com/questions/723621/how-can-i-check-if-the-cursor-is-at-the-end-of-a-line
    " ИСТОЧНИК: http://stackoverflow.com/questions/7262536/vim-count-lines-in-selected-range
    " ИСТОЧНИК: https://git.zug.fr/config/vim/blob/master/init.vim
    " ИСТОЧНИК: 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 = strchars(getline(selectionEndLine))
    let nextLineLength = strchars(getline(currentLine + 1))
    let selectionStartColumn = col("'<")
    let selectionEndColumn = col("'>")

    " Если выделение не включает или не выходит за последний видимый символ строки (также включая невидимый символ конца строки).
    if selectionEndColumn < selectionEndLineLength
        let pee="P"

        " Получает значение, если оно существует, в противном случае возвращает 0.
        if get(s:, 'debug_smart_paste')
            echomsg "SmartPaste специальный случай #1"
        endif

    " Если пытаетесь вставить на пустую последнюю строку.
    elseif selectionEndLineLength == 0 && selectionEndLine == lastLineOfBuffer
        let pee="P"

        " Получает значение, если оно существует, в противном случае возвращает 0.
        if get(s:, 'debug_smart_paste')
            echomsg "SmartPaste специальный случай #2"
        endif

    " Если выделение заканчивается после последнего видимого символа строки (также включая невидимый символ конца строки),
    " или строка визуально выбрана (Shift + V),
    " и следующая строка не пустая,
    " и выделение не заканчивается на последней строке.
    elseif selectionEndColumn > selectionEndLineLength && nextLineLength > 0 && selectionEndLine != lastLineOfBuffer
        let pee="P"

        " Получает значение, если оно существует, в противном случае возвращает 0.
        if get(s:, 'debug_smart_paste')
            echomsg "SmartPaste специальный случай #3"
        endif

    else
        let pee="p"

        " Получает значение, если оно существует, в противном случае возвращает 0.
        if get(s:, 'debug_smart_paste')
            echomsg "SmartPaste случай по умолчанию"
        endif
    endif

    let clipboard_register="+"

    " Получает значение, если оно существует, в противном случае возвращает 0.
    if get(s:, 'debug_smart_paste')
        echomsg "SmartPaste"
        echomsg "    содержимое буфера: " . getreg(clipboard_register)
        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 "    pee: " . pee
        echomsg "    границы выделения" . string([getpos("'<")[1:2], getpos("'>")[1:2]])
        echomsg "    visualmode(): " . visualmode()
        echomsg "    mode(): " . mode()
        echomsg "    getpos('.'): " . string(getpos('.'))
    endif

    try
        " Войти в режим вставки.
        " ЗАМЕТКА: Это предотвращает повторное выполнение автокоманд InsertCharPre для каждого символа в вставленной строке.
        set paste

        " Резервирование буфера обмена.
        let clipboard_contents = getreg(clipboard_register)
        let clipboard_type = getregtype(clipboard_register)

        " Если тип буфера обмена построчный.
        if clipboard_type[0] == 'V'
            " Изменить регистр буфера обмена на побуквенный режим.
            call setreg(clipboard_register, clipboard_contents, 'v')
        endif

        " Восстановите визуальное выделение с 'gv' и вставьте содержимое буфера обмена туда.
        execute 'normal! gv"' . clipboard_register . pee

        " Восстановите буфер обмена.
        call setreg(clipboard_register, clipboard_contents, clipboard_type)
    catch /E353:\ Nothing\ in\ register/
    finally
        " Выйти из режима вставки.
        set nopaste
    endtry
endfunction " }}}

function! SmartFind() " {{{
    let wordUnderCursor = expand('<cword>')
    if wordUnderCursor == ''
        execute 'promptfind'
    else
        execute 'promptfind' wordUnderCursor
    endif
endfunction " }}}

function! SmartReplace() " {{{
    let wordUnderCursor = expand('<cword>')
    if wordUnderCursor == ''
        execute 'promptrepl'
    else
        execute 'promptrepl' wordUnderCursor
    endif
endfunction " }}}

function! SmartSaveFile() " {{{
    " ИСТОЧНИК: http://vim.wikia.com/wiki/Map_Ctrl-S_to_save_current_or_new_files

    " Если файл сохранён.
    if !&modified
        return
    endif

    try
        " Если у текущего буфера нет имени.
        if empty(bufname('%'))
            " Отобразите диалог сохранения, чтобы пользователь мог указать имя файла.
            browse confirm write
        else
            " Принудительное сохранение, даже если файл с таким именем уже существует.
            confirm write
        endif
    catch /E212:\ Can't\ open\ file\ for\ writing/
        if has("win32") || has("win64")
            echomsg "ОШИБКА: У вас нет разрешения на запись для этого каталога или имя файла недопустимо."
        else
            " ЗАМЕТКА: Вызов [browse confirm write] выше установит имя файла в случае пустого буфера.
            try
                " Хак, который использует tee для вывода буфера в % имя файла с правами sudo.
                " ИСТОЧНИК: https://stackoverflow.com/questions/2600783/how-does-the-vim-write-with-sudo-trick-work
                execute("w !sudo tee %")

                if v:shell_error
                    throw 'Не удалось сохранить файл.'
                else
                    " Перезагрузите файл, иначе vim обнаружит, что файл изменился, и спросит вас о разрешении на перезагрузку файла.
                    silent edit!

                    " Очистите командную строку и уберите подсказку 'Нажмите ENTER или введите команду, чтобы продолжить'.
                    " ИСТОЧНИК: https://vim.fandom.com/wiki/Avoiding_the_%22Hit_ENTER_to_continue%22_prompts
                    redraw!
                endif
            catch /.*/
                echomsg 'SmartSaveFile() Необработанное исключение: ' . v:exception
            endtry
        endif
    endtry
endfunction " }}}

function! SmartCopyMessageHistory() " {{{
    redir @+
    silent execute(':messages')
    redir END
endfunction " }}}

" }}} Функции

" Привязки {{{

" Вставка для средней мыши в обычном, визуальном и режиме вставки {{{

" ЗАМЕТКА:  удаляет выделение из командной строки. См. :h c_CTRL-u
nnoremap <silent> <MiddleMouse> <C-v>:<C-u>call SmartPaste()<CR>

" ЗАМЕТКА:  удаляет выделение из командной строки. См. :h c_CTRL-u
vnoremap <silent> <MiddleMouse> :<C-u>call SmartPaste()<CR>

" Побуквенная вставка для режима вставки.
" ИСТОЧНИК: https://vim.fandom.com/wiki/Pasting_registers
" ЗАМЕТКА:  выполняет команду нормального режима, не покидая режима вставки. См. :help ins-special-special
" ЗАМЕТКА: + вставляет содержимое неназванного регистра во время вставки. См. :h i_CTRL-R
" ЗАМЕТКА: + не работает для столбцов текста, вырезанных и вставленных с Ctrl-v. Он принудительно вставляет выборки побуквенно. + работает.
" [плохо, срабатывает InsertCharPre для каждой вставленной буквы] inoremap <silent> <MiddleMouse> <C-r><C-r>+
" [работает] inoremap <silent> <MiddleMouse> <C-o>"+<MiddleMouse>
" [работает, но, думаю, нет необходимости в режиме вставки, потому что он не вызывает события InsertCharPre для каждой вставленной буквы] inoremap <silent> <MiddleMouse> <C-o>:set paste<CR><C-r><C-o>+<C-o>:set nopaste<CR>
inoremap <silent> <MiddleMouse> <C-r><C-o>+

" Отключите странные многократные нажатия, которые вы можете сделать с помощью средней кнопки мыши.
" ИСТОЧНИК: http://vim.wikia.com/wiki/Mouse_wheel_for_scroll_only_-_disable_middle_button_paste
nnoremap <2-MiddleMouse> <Nop>
inoremap <2-MiddleMouse> <Nop>
vnoremap <2-MiddleMouse> <Nop>
nnoremap <3-MiddleMouse> <Nop>
inoremap <3-MiddleMouse> <Nop>
vnoremap <3-MiddleMouse> <Nop>
nnoremap <4-MiddleMouse> <Nop>
inoremap <4-MiddleMouse> <Nop>
vnoremap <4-MiddleMouse> <Nop>

" }}} Вставка для средней мыши в обычном, визуальном и режиме вставки

" Если ОС не mac.
if system('uname') !~ 'Darwin' " ЗАМЕТКА: MacVim предоставляет функциональность Command+C|X|V|A|S и отмены/повтора, а также может по умолчанию Command+C|V на командную строку.
    " Копирование, вставка и выбрать все функции для командной строки {{{

    " ИСТОЧНИК: https://opensource.apple.com/source/vim/vim-62.41.2/runtime/macmap.vim.auto.html
    " ЗАМЕТКА: только копирование и вставка возможны в командной строке, насколько я могу судить.
    "       На написанный текст в командной строке нет отмены, и вы не можете вставить текст на выделение текста, чтобы заменить его.
    cnoremap <C-c> <C-y>
    cnoremap <C-v> <C-r>+

    " Все, похоже, связывают это. Нет способа выделить все, но мы можем переместить каретку в самую левую часть командной строки. Ура.
    cnoremap <C-A> <Home>

    " Копировать историю сообщений в буфер обмена.
    " ЗАМЕТКА: Это обходной путь для того, чтобы нельзя было выделить все.
    nnoremap <silent> <Leader>m :<C-u>call SmartCopyMessageHistory()<CR>

    " }}} Копирование, вставка и выбор всех функций для командной строки

    " Вырезание, копирование и вставка функции для визуального и режима вставки {{{

    " Вырезать, копировать и вставлять в визуальном режиме.
    " ИСТОЧНИК: http://superuser.com/questions/10588/how-to-make-cut-copy-paste-in-gvim-on-ubuntu-work-with-ctrlx-ctrlc-ctrlv
    " ЗАМЕТКА:  удаляет выделение из командной строки. См. :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>

    " Побуквенная вставка для режима вставки.
    " ИСТОЧНИК: https://vim.fandom.com/wiki/Pasting_registers
    " ЗАМЕТКА:  выполняет команду нормального режима, не покидая режима вставки. См. :help ins-special-special
    " ЗАМЕТКА: + вставляет содержимое неназванного регистра во время вставки. См. :h i_CTRL-R
    " ЗАМЕТКА: + не работает для столбцов текста, вырезанных и вставленных с Ctrl-v. Он принудительно вставляет выборки побуквенно. + работает, однако.
    " [работает, но, думаю, нет необходимости в режиме вставки, потому что он не вызывает события InsertCharPre для каждой вставленной буквы] inoremap <silent> <C-v> <C-o>:set paste<CR><C-r><C-o>+<C-o>:set nopaste<CR>
    inoremap <silent> <C-v> <C-r><C-o>+

    " }}} Вырезание, копирование и вставка функции для визуального и режима вставки

    " Функция выбора всего для обычного, визуального и режима вставки {{{

    " ИСТОЧНИК: http://vim.wikia.com/wiki/Using_standard_editor_shortcuts_in_Vim
    nnoremap <C-a> ggVG
    vnoremap <C-a> ggVG
    inoremap <C-a> <Esc>ggVG

    " }}} Функция выбора всего для обычного, визуального и режима вставки

    " Функция сохранения для обычного, визуального и режима вставки {{{

    nnoremap <silent> <C-s> :call SmartSaveFile()<CR>

    " ЗАМЕТКА:  удаляет выделение из командной строки. См. :h c_CTRL-u
    vnoremap <silent> <C-s> :<C-u>call SmartSaveFile()<CR>gv

    " ЗАМЕТКА:  выполняет команду нормального режима, не покидая режима вставки. См. :help ins-special-special
    inoremap <silent> <C-s> <C-o>:call SmartSaveFile()<CR>

    " }}} Функция сохранения для обычного, визуального и режима вставки

    " Функции отмены и повтора для обычного, визуального и режима вставки {{{

    nnoremap <C-z> <Esc>u
    nnoremap <C-y> <Esc><C-r>

    " ЗАМЕТКА:  удаляет выделение из командной строки. См. :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

    " Отключить клавиши отмены/повтора в нормальном режиме Vim.
    " Иметь одну клавишу для отмены - это несчастный случай, который ждет, когда произойдет, особенно когда 'u' и 'U' также используются как переключатели регистра в режиме визуального.
    " ИСТОЧНИК: https://stackoverflow.com/questions/57714401/vi-vim-remap-or-unmap-built-in-command-the-u-key-in-visual-mode
    nnoremap u <NOP>
    nnoremap <C-r> <NOP>

    " }}} Функции отмены и повтора для обычного, визуального и режима вставки

    " Функция поиска и замены для обычного, визуального и режима вставки {{{

    nnoremap <silent> <C-f> :call SmartFind()<CR>
    nnoremap <silent> <C-h> :call SmartReplace()<CR>

    " ЗАМЕТКА:  удаляет выделение из командной строки. См. :h c_CTRL-u
    vnoremap <silent> <C-f> :<C-u>call SmartFind()<CR>
    vnoremap <silent> <C-h> :<C-u>call SmartReplace()<CR>

    " ЗАМЕТКА:  выполняет команду нормального режима, не покидая режима вставки. См. :help ins-special-special
    inoremap <silent> <C-f> <C-o>:call SmartFind()<CR>
    inoremap <silent> <C-h> <C-o>:call SmartReplace()<CR>

    " }}} Функция поиска и замены для обычного, визуального и режима вставки
endif

" }}} Привязки

" }}} Общие сочетания клавиш Windows и поведение вставки
if has('patch-8.2.4881')
    xnoremap p P
    xnoremap P p
else
    xnoremap P p
    xnoremap p "_dp
endif

это работает для меня, чтобы поменять местами p и P

vnoremap p "_c<C-r>*<Esc>

Вот список моих полных привязок:

" Исправить копирование/вставку регистра  
   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<C-r>*<Esc>  

" Вставка на новой строке  
    nnoremap ,p o<Esc>p  
    nnoremap ,P O<Esc>p  

Ответ или решение

Чтобы заменить текст, выделенный в Vim, вставленной текстовой строкой без сохранения удаленных строк в буфер обмена, вы можете использовать «черную дырку» (black hole register) и специальные сопоставления. Рассмотрим поэтапно, как это сделать, а также объясним, почему это важно для более эффективной работы в редакторе Vim.

Почему это важно?

При копировании и вставке в Vim вы можете столкнуться с нежелательными последствиями: когда вы удаляете текст, он помещается в общий буфер обмена, что может вызвать путаницу при следующей операции вставки. Это может быть особенно проблематично, если вы многократно заменяете один текст другим. Использование черной дыры помогает избежать этого и обеспечивает более чистый подход.

Установка маппинга для черной дыры

Вы можете добавить следующую конфигурацию в ваш .vimrc файл, чтобы создать удобные сопоставления для этих операций:

" Настройка удаления и замены с использованием черной дыры
vnoremap p "_dP   " Вставка нового текста, не захватывая удаленный
vnoremap P "_dP   " Вставка нового текста перед текущим курсором

Объяснение конфигурации

  1. vnoremap p "_dP:

    • При выделении текста в визуальном режиме и нажатии p, Vim удаляет выделенный текст без записи его в общий буфер, добавляя его в черную дыру. Затем P вставляет содержимое, находящееся в неименованном регистре, что означает, что вы вставляете текст, который вы скопировали ранее.
  2. vnoremap P "_dP:

    • Данное сопоставление аналогично первому, но оно используется, когда вы хотите вставить текст перед текущим курсором.

Дополнительные настройки

Если вы часто нуждаетесь в этой функции, возможно, вам также стоит рассмотреть возможность использования других регистров. К примеру, использование именованных регистров может быть пригодится для копирования и вставки между множественными строками:

vnoremap y "0y   " Копировать текст в регистр 0
vnoremap p "0p   " Вставить текст из регистра 0

Альтернативные способы

Для большей гибкости вы можете использовать следующие комбинации:

  • ciw<C-r>0: Обрезает текущее слово и вставляет из регистра 0 (если вы предварительно сохранили текст, который хотите вставить).
  • <C-r><C-o>+: Это сочетание в режиме вставки позволяет вам вставлять текст из системного буфера обмена, не затрагивая другие действия.

Заключение

Данная настройка позволяет вам работать в Vim гораздо эффективнее, избегая нежелательной потери текста при замене. Использование черной дыры и регистров обеспечит вам большую гибкость и контроль над процессом замены текста. Тщательное планирование вашего ~/.vimrc файла с учетом этих настроек может значительно повысить вашу продуктивность и сделать работу с Vim более интуитивной.

Оцените материал
Добавить комментарий

Капча загружается...