Несколько курсоров в нужном месте

13

Я использую плагин vim-множественные курсоры .

Я хотел бы поставить курсоры именно там, где я хочу. Например ( [x]это позиции курсора):

Lorem ipsum dolor sit amet[1], consectetur adipiscing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna[2]
aliqua.

В Sublime Text я обычно помещал первый курсор, затем с помощью клавиш со стрелками переходил на следующую позицию и помещал второй.

Есть ли что-то похожее в VIM? С этим плагином или другим.

РЕДАКТИРОВАТЬ

После комментария мой интерес к этому проявился при попытке записи
\section[My first section in this book]{My first section in this book}
в .texфайл. Моей первой реакцией было написать \section[]{}и затем поместить два курсора, чтобы написать то же самое внутри []и {}.

Другим примером будет добавление _someStuffпосле нескольких разных имен переменных. Например, включите это:

variable1 = 2
my_variable2 = 12
var3 = 14

в это:

variable1_someStuff = 2
my_variable2_someStuff = 12
var3_someStuff = 14

С несколькими курсорами я могу сделать это, выбрав курсор на столбце и затем перейдя к концу слова, затем вставив и т. Д. Но я думаю, мне было бы легко выбрать именно то место, куда я хочу поместить курсоры.

tomasyany
источник
1
Я думаю, что важный вопрос, который нужно задать, - почему вы хотите это сделать? Что ты пытаешься сделать? Использование нескольких курсоров на самом деле не «следует Vim», возможно, существует другой способ сделать то, что вы хотите, хотя бы настолько эффективно, используя встроенные функции.
statox
@statox. Смотрите редактировать. Я привел два примера, которые пришли мне в голову. Второй я могу выполнить с помощью плагина vim-множественные курсоры, но первый я не могу, по крайней мере, в простой манере.
Томасьяны
@ Nobe4. Спасибо, второй скрипт сделал это.
Томасьяны

Ответы:

29

Использование нескольких курсоров - это не вещь Vimmer

Как я сказал в комментариях, использование нескольких курсоров (даже с плагином) на самом деле не «следует Vim», я полностью понимаю, что это привлекательно для кого-то из Sublime-Text, но вы часто можете найти альтернативы, которые по крайней мере так же эффективно со встроенными функциями Vim.

Конечно, найти эти альтернативные решения не всегда просто, а иногда это требует времени, но с вашим опытом работы с Vim это станет проще, и вы увидите, что со временем несколько курсоров покажутся вам совершенно бесполезными.

Это круто, но как найти альтернативный способ?

Универсального ответа не существует, так как это во многом зависит от того, что вы пытаетесь сделать, я просто попытаюсь дать несколько советов о первых вещах, которые нужно попробовать:


Точечная команда .

Команда Dot, вероятно, является одним из самых мощных инструментов в Vim, она просто позволяет нам повторить последнее изменение. Я не мог объяснить это лучше, чем Дрю Нейл в своей « Практической игре» . Я думаю, что каждый Vimmer должен рассмотреть возможность прочтения этой книги.

Сила этой команды в том, что последнее изменение может быть действием, работающим над символом, строкой или целым файлом. Например, изменение может быть ограничено моментом, когда вы входите в режим вставки, и моментом, когда вы возвращаетесь в нормальный режим.

Имея это в виду, легко сделать то, что вы хотели сделать с мультикурсором:

  • Сначала давайте настроим нашу среду: напишем, как вы предложили

    \section[]{}

  • Затем внесите повторяемое изменение . Курсор включен }, нажмите, F[чтобы вернуться к [персонажу. Затем войдите в режим вставки с помощью iи введите My first section in this bookи вернитесь в нормальный режим с помощью ESC:

    \section[My first section in this book]{}

  • И тут возникает волшебная часть: давайте напечатаем f{курсор, чтобы навести курсор на {персонажа, и нажмите, .чтобы повторить последнее изменение:

    \section[My first section in this book]{My first section in this book}

Вся задача команды dot состоит в том, чтобы научиться вносить повторяемые изменения: она будет сопровождаться переходом на Vim, но основная задача - понять, как вносить изменения с повторяемостью.

Например, чтобы вставить точку с запятой в конце строки, которую вы предпочитаете использовать A;вместо $a;. Почему?

Потому что A;создает атомарное действие, поэтому, когда вы будете использовать .в другой строке, независимо от того, где вы находитесь в строке, вы вставите точку с запятой в конце. Принимая во внимание, что при использовании $a;вы разделяете ваши изменения на две части, $aи, ;если вы используете .его, вы вставляете точку с запятой в текущую позицию курсора.

ПРИМЕЧАНИЕ Формула магии в Vim есть n.. Действительно крутой рабочий процесс:

  • найдите место, где вы хотите внести изменения /pattern
  • сделайте свое повторяемое редактирование
  • используйте, nчтобы перейти к следующему месту для редактирования
  • использовать, .чтобы повторить редактирование
  • повторите два последних шага: Ты король мира (или хотя бы правок)

макрос

Макросы - это еще один чрезвычайно важный инструмент в Vim, поскольку он позволяет записывать последовательность нажатий клавиш и повторять их, как если бы вы набирали их снова.

В качестве примера я буду использовать ваш второй вариант использования:

variable1 = 2
my_variable2 = 12
var3 = 14

Еще раз важно научиться делать ваши макросы эффективными (я приведу контрпример сразу после):

  • Наведите курсор на слово variable1и начните запись макроса с помощью qq. Это означает «начать запись всех моих будущих нажатий клавиш в регистр с именем q».

  • Начните редактировать набрав:

    • 0 идти в начале строки
    • e идти в конце первого слова
    • a добавить после вашего курсора
    • .someStuff добавить желаемый текст
    • <Esc> остановить вставку
    • j перейти на следующую строку
    • q прекратить запись макроса
  • Ты получишь:

variable1.someStuff = 2
my_variable2 = 12
var3 = 14
  • Теперь вы можете использовать макрос, чтобы повторить ваше редактирование. Поскольку вы находитесь на правой линии для редактирования, вы можете просто выполнить макрос с помощью @q. Поскольку мы хотим выполнить его дважды, вы можете использовать его, 2@qи вы получите следующий результат:
variable1.someStuff = 2
my_variable2.someStuff = 12
var3.someStuff = 14

ПРИМЕЧАНИЕ 1. Как вы могли заметить, использование 0eaв начале макроса было действительно важным. Действительно, если бы вы поместили курсор в конец первого слова перед записью макроса и повторным его выполнением, ваш результат был бы следующим:

variable1.someStuff = 2
my_variable2 = 12.someStuff
var3 = 14.someStuff

В качестве вашего курсора текст был бы вставлен в положение курсора после изменения строки (т.е. в конце строки в этом случае)

ПРИМЕЧАНИЕ 2 Макросы чрезвычайно эффективны, и вы можете даже создавать рекурсивные макросы, когда вам удобно с ними. Здесь ваш макрос мог бы быть:

`0ea.someStuff<Esc>j@q`

Финал @qвызвал бы макрос сам по себе вместо использования 2@q; Вы бы просто использовали, @qи вся работа была бы сделана.


визуальный блок

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

li.one   a{ background-image: url('/images/sprite.png'); }
li.two   a{ background-image: url('/images/sprite.png'); }
li.three a{ background-image: url('/images/sprite.png'); }

Что если вы переместили спрайтов из imagesв components?

Ну, вы можете навести курсор на iоф imagesи нажать <C-v>. Это запустит режим визуального блока, который позволяет выбирать блоки. Теперь вы можете напечатать, t/ чтобы выбрать слово, которое вы хотите изменить, и 2jвыбрать все вхождения слова.

После этого вам просто нужно набрать, cчтобы изменить слово, а затем components. Когда вы выйдете из режима вставки, вы увидите:

li.one   a{ background-image: url('/components/sprite.png'); }
li.two   a{ background-image: url('/components/sprite.png'); }
li.three a{ background-image: url('/components/sprite.png'); }

Глобальная команда

Глобальная команда - это инструмент, который позволяет применять команду ex mode к строкам, соответствующим шаблону, еще раз, это хороший способ применить одно и то же изменение в другом месте без необходимости использования нескольких курсоров.

Синтаксис следующий:

:[range] g / pattern / command

Для более подробной информации о [range]параметре, пожалуйста, смотрите :h :range. Я не буду подробно описывать это здесь, я просто напомню, что %представляет весь файл, '<,'> представляет последний выбор и 1,5представляет строки с 1 по 5 файла.

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

Аргумент [pattern] - это шаблон поиска, который вы привыкли использовать в поисковой системе. Поскольку он объединяет историю поиска, вы можете оставить это поле пустым, а глобальная команда будет использовать последний шаблон поиска в истории поиска.

Наконец, параметр [command] - это команда ex, к которой вы, вероятно, привыкли.

Теперь поведение глобальной команды довольно просто:

  • Итерация по всем строкам, определенным в параметре [range]
  • Если текущая строка соответствует определенному шаблону, примените команду

Поскольку параметр [command] является командой ex, вы можете делать много вещей. Давайте возьмем следующий псевдокод, который не очень интересен и содержит много сообщений отладки:

var myList  = null
var i       = 0

myList = new List()
echo "List instantiated"

for (i=0; i<10; i++)
    myList.Add(i)
    echo i . " added to the list"

echo "end of for loop"

Теперь предположим, что вы уверены, что этот код работает, и хотите удалить эти бесполезные echoоператоры:

  • Вы можете применить свою глобальную команду ко всему файлу, так что вам придется добавлять к ней команду %(или ни с чем, поскольку %это диапазон по умолчанию).

  • Вы знаете, что все строки, которые вы хотите удалить, соответствуют шаблону echo

  • Вы хотите удалить эти строки, поэтому вам придется использовать команду, :delete которая также может быть сокращена доd

Так что вам просто нужно использовать следующую функцию:

:%global/echo/delete

Который также может быть сокращен как

:g/echo/d

Обратите внимание, что %исчез, globalсокращенно как gи deleteкак d. Как вы можете себе представить, результат:

var myList  = null
var i       = 0

myList = new List()

for (i=0; i<10; i++)
    myList.Add(i)

ПРИМЕЧАНИЕ 1. Важным моментом, который мне потребовалось некоторое время, чтобы понять, является то, что normalкоманда является командой ex, что означает, что вы можете использовать ее с глобальной командой. Это может быть действительно мощным: скажем, я хочу дублировать все строки, содержащие эхо, мне не нужен макрос или даже волшебная формула n.. Я могу просто использовать

:g/echo/normal YP

И вуаля:

var myList  = null
var i       = 0

myList = new List()
echo "List instantiated"
echo "List instantiated"

for (i=0; i<10; i++)
    myList.Add(i)
    echo i . " added to the list"
    echo i . " added to the list"

echo "end of for loop"
echo "end of for loop"

ПРИМЕЧАНИЕ 2. «Эй, а если я захочу использовать мою команду в строках, которые не соответствуют определенному шаблону?»

globalимеет противоположную vglobalсокращенную команду, vкоторая работает точно так же, globalза исключением того, что команда будет применена к строкам, которые не соответствуют параметру [pattern]. Таким образом, если мы применим

:v/echo/d

На нашем предыдущем примере мы получаем:

echo "List instantiated"
    echo i . " added to the list"
echo "end of for loop"

Команда deleteбыла применена к строкам, которые не содержались echo.


Здесь я надеюсь, что эти несколько советов дадут вам идеи о том, как избавиться от вашего плагина с несколькими курсорами и использовать Vim способом Vim ;-)

Как вы можете себе представить, эти примеры довольно просты и предназначены для демонстрации того, что когда вы следуете Vim, вам действительно редко нужны несколько курсоров. Мой совет будет, когда вы столкнетесь с ситуацией, когда вы думаете, что это будет полезно, запишите ее и потратьте некоторое время спустя, чтобы найти лучшее решение. В 99% случаев вы в конечном итоге найдете более быстрый / более эффективный способ сделать это.

Также я повторюсь еще раз, но я действительно призываю вас прочитать « Практический Vim » Дрю Нила, потому что эта книга не о «Как сделать то или иное в Vim», а о «Как научиться мыслить в Vim» что позволит вам построить собственное решение ваших будущих проблем в хорошем смысле.


PS Особая благодарность @Alex Stragies за его работу по редактированию и исправления, которые он внес в этот длинный пост.

statox
источник
Очень полный ответ. Я действительно знал все эти команды, но никогда не думал об их использовании ... Думаю, мне нужно больше практиковаться. Тем не менее, я должен сказать, что иногда «vim-way» занимает больше времени, чем просто использование какого-либо плагина (например, ваш пример CSS может быть сделан намного быстрее с упомянутым плагином), а иногда это занимает гораздо меньше времени (на самом деле, огромный В большинстве случаев vim работает быстрее любого текстового редактора, если используется правильно).
Томасьяны
Кстати, я думаю, что ваш ответ уже довольно полный. Я приму это, но если вы хотите добавить больше деталей, пожалуйста, и я буду рад их прочитать.
Томасьяны
1
@tomasyany: Действительно, иногда использование «vim way» может показаться более длинным (я не могу сосчитать, сколько раз я трачу больше времени на создание рабочего макроса, чем если бы я делал изменения вручную), но с практикой это в конечном итоге становится быстрее. Я использую Vim всего один год, и я (очень) далеко не эксперт, но я чувствую, что мое редактирование постоянно улучшается по мере моей практики.
statox
1
Вероятно, следует упомянуть gnтекстовый объект. В нем рассматриваются некоторые случаи использования нескольких курсоров. Найдите с помощью /, затем dgnили cgn, затем повторите с ..
Джастин М. Киз
@ Джастин Я не очень знаком с, gnпопробую и добавлю после. Спасибо за голову!
statox
5

Мне показалось, что ваши приведенные варианты использования хотят знать .ключевую команду (повторите последнюю команду редактирования)

  • Перейти на первое место, нажмите i, вставьте свой текст,<ESC>
  • переместитесь в местоположение 2, нажмите .(точка) ==> Идентичный текст вставлен
  • Чтобы переместиться на одну строку вниз и вставить снова (при вставке в последовательные строки), нажмите <ALT>-j.

Ваш текстовый пример для меня решается с помощью:

I\section[]{}<ESC>hhiMy first Sec...<ESC>lll.

Алекс Страгиес
источник
Это довольно хорошее решение. Я прекрасно знал .ключевую команду, но никогда не думал об ее использовании таким образом. Я согласен, что это хороший способ. Но ваш ответ на самом деле не относится к реальному вопросу, поэтому было бы неправильно принять его, я думаю.
Томасьяны
1
Что ж, ваш вопрос (после того, как вы добавили нужные варианты использования) напомнил мне: «Мне действительно нравятся мои ножницы, и я хочу затянуть с ними винт. Скажите мне, как». И я указываю вам на изящное использование отвертки;) (я добавил в качестве ответа, потому что я не знаю, как сделать форматирование в комментариях)
Алекс Стрэджи
4

Больше Vim способов.

Первое задание:

\section[foobar baz]{foobar baz}

Процедура:

\section[]{}
hh
ifoobar baz<Esc>
$.

Второе задание:

variable1 = 2
my_variable2 = 12
var3 = 14

Команда:

3:norm ea_somestuff

Результат:

variable1_somestuff = 2
my_variable2_somestuff = 12
var3_somestuff = 14
romainl
источник