Как заменить вставленный текст в vim, не удаляя удаленные строки?
Поэтому я обычно копирую текст из одной точки в другую, перезаписывая старый текст, куда вставляется новый:
blah1
newtext
blah2
wrong1
blah3
wrong2
blah4
Предположим, я визуальный знак newtext
а также y
Анк это. Теперь я выбираю wrong1
(который может быть чем угодно, не обязательно просто словом) и p
Aste 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
вставить, не дергая удаленный текст.
С помощью 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