[Перевод] Заметки о Unix: одновременное редактирование нескольких файлов в Vim

Недавно мы завершили перевод последней нашей машины на новый клиент для Let«s Encrypt. В ходе работы нужно было поменять пути к выгружаемым TLS-сертификатам во всех конфигурационных файлах, где они использовались. На многих компьютерах был лишь один конфигурационный файл, но на некоторых из наших Apache-серверов пути к TLS-сертификатам имеются во множестве файлов. Поэтому я и заинтересовался вопросом о том, как, пользуясь Vim, одновременно вносить одни и те же изменения в несколько файлов. Оказалось, что Vim поддерживает такую возможность уже очень давно, причём сделать это можно несколькими способами. Некоторые из этих способов основаны на том, что я назвал бы странностью Vim. Кто-то, возможно, назовёт это архитектурной особенностью данного редактора.

uqyfqs8yvf4x7b7shrvjibqxpmk.jpeg
Чаще всего, или, точнее, когда мне приходится редактировать лишь сравнительно небольшое количество файлов, мне легче всего воспользоваться очень удобной командой : all, которая позволяет открыть окно для каждого буфера. После этого я, для применения некоей команды к каждому буферу, пользуюсь командой :windo. Например — так: :windo %s/.../.../. Потом я записываю все изменённые буферы командой :wa.

В советах по работе в Vim, касающихся поиска и замены строк в нескольких буферах и выполнения команд в нескольких буферах, можно найти сведения о команде :bufdo. Она позволяет выполнять команды для всех буферов, делая это вне зависимости от того, находятся ли они в окнах. Это я, на самом деле, попробовал в первую очередь, правда, я не пользовался возможностью записи изменённых буферов, в результате Vim остановился после того, как я внёс изменения в первый файл. Это я и считаю «исторической странностью» Vim, хотя мы с этим сразу не разобрались.

В vi уже давно имеется возможность работать с несколькими буферами, но этот редактор всегда очень внимательно относился к тому, чтобы, перед переходом к другому буферу, пользователь записывал бы изменения, внесённые в текущий буфер. Тут легко прослеживается связь такого поведения редактора с теми временами, когда им пользовались на маленьких, сравнительно сильно нагруженных машинах, для которых и создавался vi. Дело в том, что пустой буфер — это буфер, который не надо хранить в памяти или в файле подкачки на диске (и при таком подходе никто ничем не рискует в том случае, если vi или сам компьютер вдруг даст сбой). Но в наши дни это не соответствует тому, как большинство других редакторов, поддерживающих работу с несколькими файлами, подходят к решению аналогичной задачи. Большинство таких редакторов позволяют пользователю держать открытыми сколько угодно много изменённых буферов. Такие редакторы при этом ни на что не жалуются, не говоря уже о том, чтобы заставлять пользователя сохранять один буфер перед переходом к другому, или не давать открывать новые буферы. То, что такие редакторы не вмешиваются в действия пользователя, немного облегчают работу с ними, и Vim в этом плане немного непоследователен, так как содержимое окна может быть изменено, но это не мешает пользователю переключиться на другое окно.

Если учесть мою точку зрения на происходящее, то я, возможно, решил бы включить опцию hidden. Ну, если только я был бы совершенно уверен в выполненных мной изменениях файлов. Мне не хочется добавлять | update к команде :bufdo для немедленной записи изменений. А включение опции hidden приближает поведение Vim к поведению других редакторов. Недостатки такого подхода, о которых идёт речь в документации Vim, к моей работе отношения не имеют. Я пользуюсь командами :q! или :qa! только тогда, когда совершенно уверен в том, что хочу отказаться от всех несохранённых изменений.

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

:hide bufdo %s/.../.../

Полагаю, нет идеального способа отмены последствий операции по изменению нескольких файлов, результат которой оказался не таким, как хотелось бы. Если все буферы пребывали в исходном состоянии до выполнения команд bufdo или windo, можно снова воспользоваться соответствующей командой для вызова undo в каждом из буферов (:bufdo u). При наличии неизменённых буферов это никак мне не повредит в том случае, если в ходе операции над несколькими файлами некий файл окажется неизменённым. Правда, если в некоторых буферах есть несохранённые данные, такая операция становится опасной, так как команда undo, выполняемая в каждом из буферов, довольно-таки ограничена. А именно, отменены будут только самые свежие изменения, вне зависимости от их связи с самой первой командой bufdo.

(Всё это говорит мне о том, что мне стоит внимательно перечитать (или просто прочесть) вопросы и ответы по работе с буферами Vim, так как в том, как в Vim организована работа с буферами, файлами, вкладками и окнами, кое-что мне не вполне ясно. GNU Emacs в подобных вопросах тоже, на свой лад, не до конца мне понятен, но, пользуясь им, я, по крайней мере, могу ориентироваться в истории.)

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

Пользуетесь ли вы Vim?

© Habrahabr.ru