У Vim існує спосіб видалення, не вносячи текст до реєстру?


470

Використовуючи Vim, я часто хочу замінити блок коду на той блок, який я щойно викрутив.

Але коли я видаляю блок коду, який підлягає заміні, сам цей блок переходить до реєстру, який стирає блок, який я щойно вирвав. Тож у мене звичка дзижчати, то вставляти, то видаляти те, що я не хотів, але з великими блоками коду це стає безладним, намагаючись утримати вставлений блок, а блок видалити окремо.

То який найрізший і швидкий спосіб замінити текст у Vim?

  • чи є спосіб видалити текст без внесення його до реєстру?
  • чи є спосіб сказати, наприклад, "замінити наступне слово" або "замінити на наступний абзац"
  • або це найкращий спосіб якось використовувати функцію мультиреєстру?

1
vim-easyclip ( github.com/svermeulen/vim-easyclip ) призначений для вирішення цієї точної проблеми
Стів Вермеулен

1
Я задав запитання, несвідомо (на той час) дублікат вашої реальної проблеми , але не так багато заголовкового питання. TL; DR - замініть тим, що ви дробили, використовуючи viwp(для word).
OJFord

Відповіді:


429

Щоб видалити щось, не зберігаючи його в реєстрі, ви можете скористатися "регістром чорної діри":

"_d

Звичайно, ви можете також скористатися будь-яким іншим регістром, який не містить нічого цікавого.


4
Спочатку я подумав, що ця команда не працює належним чином. Тоді я зрозумів, що використовую американську клавіатуру "мертвих клавіш". За допомогою цієї розкладки клавіатури я маю набрати "<space>_d. Місце для введення
тексту

4
Будь-які ідеї робити це вибірково лише на порожніх рядках? (Якщо я ddна порожньому рядку, він переходить в чорний отвір, інакше це ddяк нормально).
Джонатан Дюман

6
Щоб видалити один символ, спробуйте:"_x
kenorb

54
Це одна область, де перемагає стандартний текстовий редактор. Ви просто натискаєте клавішу видалення.
Вінс Пануччо

22
Ви також можете yyвитягнути щось за допомогою "3yy" (або будь-якого іншого), що додає його до реєстру без назви, але також у 0. Потім ви можете продовжувати вставляти його "0p, незважаючи на те, що використовували dпісля цього.
Halfgaar

102

Так. Це трохи складніше, ніж спочатку видалити "старий" текст, але:

Я починаю з ..

line1
line2
line3
line4

old1
old2
old3
old4

Я shift+ vвиберіть рядок1, рядки 2, 3 та 4 та видаліть їх dкомандою

Потім я видаляю старі 1-4 рядки так само.

Тоді, зробіть

"2p

Це вставить другий останній викреслені лінії (рядок 1-4). "3pзробить третій-з-останнього тощо.

Так я закінчую

line1
line2
line3
line4

Довідка: документація Vim на нумерованому регістрі


Якщо ви вибираєте рядки з <Shift-v>, ви видаляєте їх лише з d, а не dd
Heikki Naski

31
Від 1 до 9 працює для видалення. Щоб вставити останню річ, дійсно потріскану (з 'y'), ви повинні використовувати "0p. Це корисно в тих випадках, коли ви спочатку витріщаєте щось, що має намір замінити щось інше, але потім щось інше замінює реєстр вставки за замовчуванням.
Rafael de F. Феррейра

Для додаткової перевірки скасування витонченості з в Гундо (графічний відмін) сценарію .
Лумі

@ RafaeldeF.Ferreira: Ваш коментар не є відповіддю на це питання, але він фактично вирішує, мабуть, актуальну проблему, яка змусила ОП задати це питання в першу чергу. Для мене це була справжня проблема.
0xc0de

76

Документи VIM: Нумерований регістр 0 містить текст останньої команди yank, за винятком випадків, коли команда вказала інший регістр з ["x].

Наприклад, ми беремо "foo" та видаляємо "bar" - реєстр 0 все ще містить "foo"! Отже, "foo" можна вставити за допомогою"0p


53

Це зручно мати просте відображення, яке дозволяє замінити поточний вибір буфером.

Наприклад, коли ви поміщаєте це у свій .vimrc

vmap r "_dP       // it's a capital 'p' on the end

потім, скопіювавши щось у реєстр (тобто з 'y'), ви можете просто вибрати текст, який ви хочете замінити, і просто натиснути 'r' на клавіатурі. Виділення буде замінено вашим поточним регістром.

Пояснення:

vmap - mapping for visual mode
"_d - delete current selection into "black hole register"
P - paste

1
Для більш просунутою версією, перевірте: stackoverflow.com/questions/290465 / ...
Люк Hermitte

Я хотів би скористатисяvmap <C-P> "_dP
Гаррі Лі

7
Ви можете просто помістити текст, не видаляючи виділення. Наприклад, Vpзамінює поточний рядок одразу витягнутий.
Боббі Маринофф

Це рішення не виправляє проблему d, яка часто використовується для видалення.
Віктор Ярема

35

Я помістив у свій vimrc наступне:

noremap  y "*y
noremap  Y "*Y
noremap  p "*p
noremap  P "*P
vnoremap y "*y
vnoremap Y "*Y
vnoremap p "*p
vnoremap P "*P

Тепер я підбираюсь до реєстру буфера обміну і кладу його, і мені не потрібно байдуже, що відбувається з регістром за замовчуванням. Додатковою перевагою є те, що я можу вставляти інші програми з мінімальними клопотами. Я втрачаю деяку функціональність, я знаю, але я все одно не можу відслідковувати більш ніж один реєстр / буфер обміну.


6
Замість усіх цих перестановок ви також можете set clipboard=unnamedабо set clipboard=unnamedplus, що змінює буфер обміну за замовчуванням на *або +, відповідно.
Стів

5
@Steve Якщо ви це зробите, то d перезаписує останній ярлик до реєстру буфера обміну, чого саме намагається уникати.
79E09796

1
@ 79E09796, я не мав на увазі, що це буде; Я коментував цю відповідь, а не оригінальне запитання.
Стів

1
Я помістив їх у свій .vimrc, і тепер янка не працює. Будь-яка ідея чому?
tba

2
@tba замініть noremap на nnoremap (два n-х), і це повинно працювати нормально.
meain

24

Для конкретного прикладу, який ви навели, якщо я розумію питання, то це може спрацювати:

*Highlight what you want to put somewhere else
*delete (d)
*Highlight the code that you want it to replace
*paste (p)

6
Це добре працює, за винятком випадків, коли ви хочете вставити кілька варіантів.

23

Усі операції по витягуванню та видаленню за замовчуванням записуються до безіменного регістра. Однак найновіший випуск та останнє видалення завжди зберігаються (окремо) у нумерованих регістрах. Реєстр 0містить найсвіжіший вибій. Регістри 1-9містять 9 останніх видалених (при 1цьому є останніми).

Іншими словами, видалення замінює найновіший випуск у неназваному реєстрі, але він все ще є в 0реєстрі. Трюк з реєстрацією чорної дуги ( "_dd), згаданий в інших відповідях, працює, оскільки він перешкоджає перезаписуванню неназваного реєстру, але це не обов'язково.

Ви посилаєтесь на реєстр, використовуючи подвійні лапки, тому вставку останнього вилученого тексту можна зробити так:

"0p

Це відмінна довідка:


16

Щоб підкреслити те, що сказав EBGreen :

Якщо ви вставляєте текст під час вибору тексту, вибраний текст замінюється на вставлений текст.

Якщо ви хочете скопіювати якийсь текст, а потім вставити його в декілька місць, використовуйте його "0pдля вставки. Нумерований регістр 0 містить текст останньої команди yank.


Також ви можете перелічити вміст усіх своїх реєстрів:

:registers

Ця команда полегшує зрозуміти, який реєстр ви хочете, виконуючи щось на зразок відповіді dbr . Ви також побачите регістри /,%, #. (Див. Також :help registers)


І нарешті, перевірте cWі cWзмінити слово, включаючи та не включаючи пробіл. (Використання капіталу Wвключає розділові знаки.)


10

Якщо ви використовуєте Vim, у вас з'явиться візуальний режим, який схожий на вибір, але з розділюючими режимами, що є основою vi / vim.

Що ви хочете зробити, це скористатися візуальним режимом для вибору джерела, потім вимкнути, потім знову використовувати візуальний режим, щоб вибрати область призначення, а потім вставити текст з буфера за замовчуванням.

Приклад:

У текстовому файлі з:

1 | qwer
2 | asdf
3 | zxcv
4 | poiu

із такою послідовністю: ggVjyGVkpви закінчите:

1 | qwer
2 | asdf
3 | qewr
4 | asdf

Пояснили:

  • gg: перейти до першого рядка
  • V: запустіть візуальний режим цілими рядками
  • j: вниз на один рядок (при виборі, розпочатому в попередніх рядках, це збільшує вибір на один рядок вниз)
  • y: yank до буфера за замовчуванням (два вибрані рядки, і він автоматично виходить з візуального режиму)
  • G: перейти до останнього рядка
  • V: запуск візуального режиму (такий же, як і раніше)
  • k: перехід на одну лінію (як і раніше, із увімкненим візуальним режимом, це збільшує вибір на одну лінію вгору)
  • p: вставити (з виділенням у двох останніх рядках, він замінить ці рядки тим, що є в буфері - 2 перші рядки в цьому випадку)

Це мало незручно, що ставить останній блок на буфер, тому якимось чином не бажано для повторних вставлень одного і того ж, тому ви хочете зберегти джерело у названому буфері з чимось подібним "ay(до буфера під назвою "a ") і вставити щось подібне "ap(але тоді, якщо ви програмуєте, ви, ймовірно, не хочете вставляти кілька разів, а створити функцію та викликати її, правда? ПРАВО ?).

Якщо ви використовуєте лише vi, тоді вам доведеться використовувати невидимі позначки замість візуального режиму, :he markдля більш детального про це, пробачте, але мені не дуже добре з цією невидимою позначкою, я дуже забруднений візуальним режимом.


10

Для "замінити слово" спробуйте cwв звичайному режимі.

Для "заміни абзацу" спробуйте capв звичайному режимі.


1
Для "заміни на наступний абзац" спробуйте c}в звичайному режимі.
jabirali

Чому "шапка" робить це? Хіба не "a" та "p" означають "додавання" та "вставити"?
WiSaGaN

2
@WiSaGaN "ap" означає "абзац": vimhelp.appspot.com/motion.txt.html#object-select
CH

9

Мінімально інвазивне рішення для ледачих:

Реєстрація 0завжди містить останній yank (як вже згадували Rafael , alex2k8 та idbrii ). На жаль, вибір реєстру 0весь час може бути дуже дратівливим, тому було б непогано, якщо pвикористовується "0за замовчуванням. Цього можна досягти, помістивши у ваш ряд наступні рядки .vimrc:

noremap p "0p
noremap P "0P
for s:i in ['"','*','+','-','.',':','%','/','=','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
    execute 'noremap "'.s:i.'p "'.s:i.'p'
    execute 'noremap "'.s:i.'P "'.s:i.'P'
endfor

Перший рядок відображає кожен pштрих до "0p. Однак це не дозволяє pотримати доступ до будь-яких інших регістрів. Тому всі pштрихи з явно вибраним регістром відображаються в еквівалентний вираз командного рядка в циклі for-loop. Те ж саме робиться і для P.

Таким чином зберігається стандартна поведінка, за винятком неявних pта Pштрихів, які тепер використовують регістр 0за замовчуванням.

Підказка 1: команда вирізання тепер "0dзамість просто d. Але оскільки я лінивий, це для мене занадто довго;) Тому я використовую таке відображення:

noremap <LEADER>d "0d
noremap <LEADER>D "0D

Клавіша лідера \за замовчуванням, тому ви можете легко вирізати текст, набравши \dабо \D.

Підказка 2: Час очікування для відображення кількох клавіш за замовчуванням досить короткий. Ви можете збільшити його, щоб мати більше часу під час вибору реєстру. Детальніше :help timeoutlenдив. Я використовую:

set timeout timeoutlen=3000 ttimeoutlen=100

7

Ну, спочатку виконайте цю команду:

:h d

Тоді ви зрозумієте, що можете видалити в конкретний реєстр. Таким чином, ви не зміните те, що є у вашому реєстрі за замовчуванням.


1
["x]d{motion} Delete text that {motion} moves over [into register x]- Vim:h d
Уес Тернер

5

Моя ситуація: у Normalрежимі, коли я видаляю символи за допомогою xнатискання клавіші, ці вилучення перезаписують мій останній реєстр - ускладнюючи редагування, де я хочу видалити символи, використовуючи xі вставити те, що є у моєму останньому реєстрі (наприклад, вставлення одного і того ж тексту в два або більше місць).

Я спробував пропозицію у прийнятій відповіді ( "_d), але це не вийшло.

Однак із прийнятої відповіді / коментарів на /vi/122/performing-certain-operations-without-clearing-register я додав це до свого ~/.vimrc, що працює (можливо, доведеться перезапустити Vim ):

nnoremap x "_x

Тобто зараз я можу виконувати свої звичайні команди yank ( y), delete ( d) та вставляти ( p) - і символи, які я видаляю, використовуючи xбільше, не заповнюють останні регістри.


4

Текст видалений, перебуваючи у режимі вставки, не переходить у реєстр за замовчуванням.


2
але видалення будь-якої значної кількості тексту в режимі за замовчуванням є ПОЛОЖЕННЯ
Хаміш Даунер

3

Два рішення, які я використовую у правильних контекстах, є;

  • виділіть те, що ви хочете замінити в VISUALрежимі Vims, а потім вставити регістр.

Я використовую це в основному за звичкою, оскільки я знайшов лише друге рішення набагато пізніше, наприклад

yiw   " yank the whole word
viwp  " replace any word with the default register
  • YankRing . За допомогою цього плагіна ви можете використовувати прив'язку клавіш <ctrl>+<p>для заміни попереднього нумерованого регістра на той, який ви щойно вставили.

В основному ви займаєтеся вставкою так, як хотіли б, але коли зрозумієте, що з тих пір ви перезаписали регістр за замовчуванням, втрачаючи те, що ви насправді хотіли вставити, ви можете <C-P>знайти та замінити з історії YankRing!

Один з них повинен мати плагіни ...



2

У версії Windows (напевно, і в Linux) ви можете потрапити в буфер копіювання / вставки системи, використовуючи "*y(тобто, передуючи команді yank з подвійними лапками і зірочкою).

Потім ви можете видалити зміни, що змінюються, і вставити скопійований текст за допомогою "*p.


2

Я часто помиляюся, коли слідую за командами "y'ank then" "_d'elete в чорну діру, то" p'aste. Я вважаю за краще "y'ank, а потім видаляю все, що мені подобається, потім" "0p" з регістр 0, куди потрапляє останній скопійований текст.


2

Для зловмисників emacs функція (evil-paste-pop)може бути запущена після вставки та циклів за допомогою попередніх записів у програмі kill-ring. Якщо припустити, що ви зв'язали його <C-p>(за замовчуванням у Spacemacs), ви б потрапилиp потім стільки , скільки <C-p>необхідно.


1

Для користувачів Дворака одним дуже зручним методом є просто видалити непотрібний текст у регістрі "1 замість" _ регістру чорної діри, хоча б тому, що ви можете натиснути "+ 1 тим самим натисканням зсуву та швидким руйнівним рухом, оскільки 1 є клавіша, що знаходиться вгорі "в Двораку (PLUS d - з іншого боку, що робить всю команду швидкою як пекло).

Тоді, звичайно, "1 реєстр може бути використаний для інших речей через його зручність, але якщо ви не маєте мети, звичайнішої за заміну тексту, я б сказав, що це досить добре використовувати реєстр.


1

Для тих із вас, хто в першу чергу зацікавлений у тому, щоб не замінювати реєстр неназваних під час заміни тексту за допомогою віртуального вибору та вставки.

Ви можете використати таке рішення, яке легко і найкраще працює для мене:

xnoremap <expr> p 'pgv"'.v:register.'y'

Це з відповідей (та коментарів) тут: Як вставити без перезапису регістра

Спочатку він проходить виділення, потім вибирається новий текст знову (gv). Тепер реєстр, який востаннє використовувався у візуальному режимі (зазвичай це неназваний реєстр, але працює також без побічних ефектів, якщо ви використовуєте інший регістр для вставки). А потім знову дістати нове значення до регістра.

PS: Якщо вам потрібен більш простий варіант, який працює також з vim-імітацією плагіна intellj idea, ви можете взяти цей (недолік: перезаписати неназваний реєстр, навіть якщо інший реєстр був наданий для вставки):

vnoremap p pgvy


1

Для тих, хто використовує JetBrans IDE (PhpStorm, WebStorm, IntelliJ IDEA) з IdeaVim. Можливо, у вас виникли проблеми з перезастосуванням на кшталт nnoremap d "_dі використанням його для видалення рядка dd. Можливе рішення для вас:nnoremap dd "_dd

На youtrack є проблеми, будь ласка, проголосуйте за них: https://youtrack.jetbrains.com/issue/VIM-1189 https://youtrack.jetbrains.com/issue/VIM-1363


0

Іноді перевагу Vim щодо складності перед практичністю обтяжує користувача застосуванням регістрів для копіювання / видалення дій - коли найчастіше потрібно просто вставити те, що було скопійовано, та «забути» те, що було видалено.

Однак замість того, щоб боротися зі складними регістрами vim, зробіть їх зручнішими: виберіть реєстр "за замовчуванням" для зберігання останнього видалення. Наприклад, надішліть видалених в регістр d (залишаючи AC відкритим для спеціального використання; d - хороша мнеміка):

nnoremap d "dd           "send latest delete to d register
nnoremap D "dD           "send latest delete to d register 
nnoremap dd "ddd         "send latest delete to d register
nnoremap x "_x           "send char deletes to black hole, not worth saving
nnoremap <leader>p "dp   "paste what was deleted
nnoremap <leader>P "dP   "paste what was deleted

Такий підхід запобігає виправленням клопоту делетів, АЛЕ не втрачає реєстрації видалення - можна вставити (повернути) те, що було видалено, замість того, щоб втратити його у чорній дірі (як у прийнятій відповіді). У наведеному вище прикладі це відкликання робиться за допомогою двох відображень лідерів p. Перевага такого підходу полягає в тому, що він дає вам можливість вибирати те, що потрібно вставити: (а) те, що щойно було вирвано, або (б) те, що тільки що було видалено.


0

зареєструйте 0 до 9 - це останні речі, які ви дбаєте чи вирізаєте тощо, і НЕ включайте видалені речі тощо. Отже, якщо ви щось витягуєте / вирізаєте, він також є в реєстрі 0, навіть якщо ви скажете видалені речі весь день після цього, зареєструйте 0 - це все-таки останній матеріал, який ви викрутили / вирізали.

ініціюйте #goes як в регістрі за замовчуванням, так і зареєструйте 0

воно дрімає слово, в якому знаходиться курсор

видалені речі тощо перейдуть до реєстру за замовчуванням, але НЕ реєструють 0

в стандартному режимі:

"0p # введіть вміст регістра 0

у режимі вставки:

ctrl-r 0 # введіть вміст регістра 0

У мене також був друг, який завжди дрочив / вирізав, щоб зареєструвати x lol.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.