Хабрахабр

[Перевод] История Vim и руководство по его эффективному использованию

Примечание от переводчика: это первая часть монументальной (на самом деле монументальной) статьи о Vim и его возможностях от разработчика из Миннеаполиса и автора проекта PostgREST Джо begriffs Нельсона.

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


Эта статья основана на исследовании истории Vim и прочтении его руководства пользователя от корки до корки. Надеюсь, эти заметки помогут вам открыть (или переоткрыть?) для себя основные функциональные возможности этого редактора, а также позволят отказаться от использования предупакованных файлов vimrc и более вдумчиво использовать плагины.

Список литературы

Чтобы выйти за границы привычных тем, я бы порекомендовал обзавестись бумажной копией этого руководства и емким карманным справочником. Я не смог найти печатную копию руководства пользователя для Vim, так что в итоге просто распечатал идущий вместе с редактором PDF-файл с помощью printme1.com. Он идет вместе с софтом в $VIMRUNTIME/doc/usr_??. В качестве удобного списка команд могу посоветовать справочник «Vi and Vim Editors Pocket».

Содержание

  • История
  • Иерархия конфигурации
  • Сторонние плагины
  • Бекапы и откаты
  • Include и path
  • Редактирование и компиляция цикла
  • Диффы и патчи
  • Буфер ввода / вывода
  • Типы файлов
  • Не забывайте про мышь
  • Разное

История

Рождение vi

Команды и функции Vi существуют уже более пятидесяти лет, начиная с редактора QED. Вот его таймлайн:

  • 1966: QED («Быстрый редактор») в Berkeley Timesharing System
  • 1969 июл: с его помощью проводили посадку на Луну (ну так, для справки)
  • 1969 Авг: QED → ed в AT&T
  • 1976 Фев: ed → em («Editor for Mortals») в колледже королевы Марии
  • 1976: em → ex («EXtended») в Калифорнийском университете в Беркли
  • 1977 окт: ex получает визуальный режим, vi — текстовый терминал

Если вы почитаете руководство по QED и ex, то сможете обнаружить между ними некоторое сходство. Оба редактора используют схожу грамматику для указания и работы с диапазонами строк.

Такие «полнокопирные» терминалы выводили команды на бумагу и очевидно, после ввода внести какие-либо исправления было невозможно. Такие редакторы как QED ed и em разрабатывались для печатных терминалов, которые в основной своей массе были обычными электрическими пишущими машинками с подключенным к ним модемом. Поэтому процесс редактирования заключался в ручных правках пользовательских команд на бумаге, а после — повторного ввода.

В Ex-редактор добавили «открытый режим», который позволял редактирование через видеотерминал в рамках одной страницы. К 1976 году появились видеотерминалы, например, ADM-3A. Визуальный режим активировался командой «vi» и постоянно обновлял отображаемый на экране файла, сохраняя при этом позиционирование командной строки в нижней части экрана. Был добавлен и визуальный режим для ориентирования на строках терминала с помощью курсора. Интересный факт: на клавишах h, j, k, l на ADM-3A были нанесены стрелки, которые позволяли перемещать курсор в vi.

В нем он рассказывает о том, как создал ex/vi и о некоторых вещах, которые в итоге его разочаровали. Узнать больше об этом периоде перехода от ed к ex/vi можно в интервью Билла Джоя.

Оба представлены одним и тем же двоичным файлом, который может запускаться как в ex-режиме, так и vi-режиме в зависимости от имени исполняемого файла. Классический vi — это просто альтер-это ex. Он также доступен в большинстве существующих систем и полностью описан в POSIX. Наследие всей этой истории в том, что ex / vi «раскрывается» при использовании, почти не требует системных ресурсов и может работать в условиях ограниченной полосы пропускания.

От vi к Vim

Будучи производным от ed, редактор ex / vi являлся интеллектуальной собственностью AT&T. Чтобы использовать vi на платформах, отличных от Unix, люди должны были писать клоны, которые имели другую кодовую базу исходника.

Вот некоторые из них:

  • nvi — 1980 для 4BSD
  • calvin — 1987 для DOS
  • vile — 1990 для DOS
  • stevie — 1987 для Atari ST
  • elvis — 1990 для Minix и 386BSD
  • vim — 1991 для Amiga
  • viper — 1995 для Emacs
  • elwin — 1995 для Windows
  • lemmy — 2002 для Windows

Мы сосредоточимся на клоне из центра списка — Vim. Брэм Муленаар хотел использовать vi на Amiga и начал переносить с Atari и развивать клона vi «stevie». А назвал он свою версию порта «Vi Imitation». Если хотите узнать об этом процессе из первых рук, то посмотрите его интервью для Free Software Magazine.

22 Vim был переименован в «Vi IMproved», что указывает на превосходство копии над оригиналом. В версии 1. Вот график следующих основных версий с описанием некоторых функций:

Чтобы увидеть планируемые обновления, а так же список известных ошибок, стоит обратиться к todo.txt. Для получения дополнительной информации о каждой версии стоит курить help, например, для vim8.

Разработчики последнего хотели запускать отладку и REPL для веб-сценариев прямо внутри редактора. Например, восьмая версия включала некоторую поддержку асинхронных заданий по причине давления на проект со стороны NeoVim.

Приспосабливаясь всю историю своего существования к работе на абсолютно разных платформах, этот редактор был вынужден держаться в рамках «легкой» культуры кодинга. Вообще Vim суперпортативный. Вы можете положиться на Vim где угодно, и плевать, какое оборудование вы используете. Vim работает на OS / 390, Amiga, BeOS и BeBox, Macintosh Classic, Atari MiNT, MS-DOS, OS / 2, QNX, RISC-OS, BSD, Linux, OS X, VMS и MS-Windows.

Сорцы доступны по адресу ex-vi.sourceforge.net. В конце пути оригинального vi, в 2002 году, исходный код ex / vi все же был опубликован под лицензией свободного программного обеспечения BSD.

Прежде чем начать анализ Vim, полезно знать, как он организует и читает свои файлы конфигурации. Но давайте перейдем к делу.

Иерархия конфига

Раньше я ошибочно считал, что Vim достает все свои настройки и сценарии только из файла .vimrc. Просмотр репозиториев случайных «дотфайлов» может только укрепить в этом мнении. Довольно часто люди выкладывают чудовищные по своей сути одиночные файлы .vimrc, задача которых — контроль каждого аспекта редактора. Эти громадные конфиги еще иногда называют «vim distros».

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

:scriptnames

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

Если вы установили множество плагинов, то редактору предстоит и многое сделать. Список оказался длиннее, чем вы ожидали? Проверьте, что замедляет его работу при запуске, выполнив следующую команду создания start.log:

vim --startuptime start.log name-of-your-file

Просто сравните, как быстро Vim запускается с из коробки:

vim --clean --startuptime clean.log name-of-your-file

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

Проверьте путь выполнения в своей системе через эту команду:

:set runtimepath

Моя система содержит следующие каталоги, указанные по умолчанию для runtimepath-проверки. Не все из них даже существуют, но Vim все равно будет пытаться обратиться к ним и станет проверять содержимое, если они все же на месте:

~/.vim
Домашний каталог, предназначен для созданных профилей.

/usr/local/share/vim/vimfiles
Общесистемный каталог Vim, для профилей с правами системного администратора.

/usr/local/share/vim/vim81
Aka $ VIMRUNTIME, для файлов, распространяемых вместе с Vim.

Он предназначен для добавления персональных настроек системного администратора «по умолчанию». /usr/local/share/vim/vimfiles/after
В общесистемном каталоге Vim есть еще каталог «after».

Нужен для того, чтобы личные конфиги не отменяли или не пересекались с общесистемным или настройками «по умолчанию». ~/.vim/after
Каталог «after» в домашнем каталоге.

Этот всегда стоит в конце списка и обрабатывается последним. Вообще каталоги обрабатываются в том же порядке, в котором они записаны в start.log, исключение сделано только для «after».

Чтобы больше узнать об этом, посмотрите help runtimepath. При обработке каждого каталога, Vim ищет в них подпапки с конкретными именами. Вот краткое описание тех, которые мы будем рассматривать далее по тексту:

Еще их называют «глобальными». plugin /
Тут лежат файлы сценариев Vim, которые автоматически загружаются при редактировании любого типа файла.

Эти скрипты автозагрузки содержат функции, которые подтягиваются только по запросу других скриптов. autoload /
(Не путать с «plugin»).

В своей работе они опираются на расширение, расположение или внутреннее содержимое файла. ftdetect /
Скрипты для определения типов файлов.

ftplugin /
Скрипты, которые выполняются при редактировании файлов известного типа.

Может быть разделен сразу между несколькими ftplugins. compiler /
Определяет, как запускать различные компиляторы или lint-проверку, и как анализировать их вывод. Compiler не выполняется автоматически и должен вызываться командой.

Имеет собственную систему упаковки, не требует для работы стороннего кода. pack /
Контейнер для собственных пакетов Vim 8, преемник управления пакетами в стиле Pathogen.

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

Сторонние плагины

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

На vim.org был реестр плагинов как минимум до 2003 года включительно (если архив не врет). Именно для решения этого вопроса и стали развиваться «менеджеры плагинов». Однако в моду «менеджеры плагинов» как сущность вошли только к 2008 году.

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

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

  • Mar 2006 — Jul 2014: Vimball
  • Oct 2008 — Dec 2015: Pathogen
  • Aug 2009 — Dec 2009: Vimana
  • Dec 2009 — Dec 2014: VAM
  • Aug 2010 — Nov 2010: Jolt
  • Oct 2010 — Nov 2012: tplugin
  • Oct 2010 — Feb 2014: Vundle
  • Mar 2012 — Mar 2018: vim-flavor
  • Apr 2012 — Mar 2016: NeoBundle
  • Jan 2013 — Aug 2017: infect
  • Feb 2013 — Aug 2016: vimogen
  • Oct 2013 — Jan 2015: vim-unbundle
  • Dec 2013 — Jul 2015: Vizardry
  • Feb 2014 — Oct 2018: vim-plug
  • Jan 2015 — Oct 2015: enabler
  • Aug 2015 — Apr 2016: Vizardry 2
  • Jan 2016 — Jun 2018: dein.vim
  • Sep 2016 — Present: native in Vim 8
  • Feb 2017 — Sep 2018: minpac
  • Mar 2018 — Mar 2018: autopac
  • Feb 2017 — Jun 2018: pack
  • Mar 2017 — Sep 2017: vim-pck
  • Sep 2017 — Sep 2017: vim8-pack
  • Sep 2017 — May 2019: volt
  • Sep 2018 — Feb 2019: vim-packager
  • Feb 2019 — Feb 2019: plugpac.vim

Первое, на что нужно обратить внимание в списке выше — это огромное разнообразие. Второе — каждый из представленных инструментов «живет» примерно четыре года, а потом, по всей видимости, выходит из моды.

Давайте рассмотрим, как это делать. Путь наименьшего сопротивления в управлении плагинами — это просто использовать встроенную функциональность Vim 8, которая не требует подтягивания какого-то стороннего кода.

Для начала создайте две директории внутри вашего runtimepath: opt и start.

mkdir -p ~/.vim/pack/foobar/

Обратите внимание на плейсхолдер «foobar» (имя можно изменить). Он полностью классифицирует все пакеты, которые попадут внутрь. Большинство пользователей просто сбрасывают все свои плагины в какую-нибудь одну категорию и, в общем-то, это нормально. Выберите любое имя, которое вам нравится; Я продолжу использовать foobar. В теории, вы также можете создать несколько категорий, например ~/.vim/pack/navigation и ~/.vim/pack/linting. Обратите внимание, что Vim не распознает дублирование между категориями и дважды загружает дубликаты, если они существуют.

Эта опция хороша для редко используемых пакетов и поддерживается Vim «из коробки», без необходимости запуска скриптов. Пакеты в «start» загружаются автоматически, тогда как пакеты в «opt» не загружаются до тех пор, пока они не будут из в Vim с помощью команды :packadd. Обратите внимание, что у :packadd нет аналога для выгрузки пакетов.

Загрузите и распакуйте его последнюю версию по адресу: Для рассмотрения этого примера мы добавим плагин нечеткого поиска ctrlp в opt.

curl -L https://github.com/kien/ctrlp.vim/archive/1.79.tar.gz \ | tar zx -C ~/.vim/pack/foobar/opt

Эта команда создаст папку ~ / .vim / pack / foobar / opt / ctrlp.vim-1.79 и выгрузит готовый к использованию пакет. Вернитесь в vim и создайте указатели справочных тегов (helptags index) для нового пакета:

:helptags ~/.vim/pack/foobar/opt/ctrlp.vim-1.79/doc

Эта команда создаст файл с именем «tags» в папке с сорцами пакета, которые делают темы доступными для просмотра во внутренней системе Vim. Альтернативный путь: запустить helptags ALL после загрузки пакета, и команда позаботится обо всех файлах и их путях выполнения.
Когда вы захотите использовать пакет, просто загрузите его и помните, что в этом случае работает завершение с помощью табуляции, так что полное имя вводить не потребуется:

:packadd ctrlp.vim-1.79

Базовый каталог Packadd лежит в runtimepath, что позволяет ему использовать сценарии его плагина и ftdetect. После загрузки ctrlp вы сможете использовать команду CTRL-P, чтобы открыть поиск файлов по частичному совпадению.

Я же, со своей стороны, просто распаковываю пакеты из tar-архивов и отслеживают их по репозиторию вручную. Некоторые люди следят за своим каталогом ~ / .vim и для контроля версий каждого пакета используют git. Если вы используете достаточно зрелые пакеты, которые не требуют частых обновлений, а также скрипты, то они достаточно маленькие и не загромождают историю git.

Бэкапы и откаты версий

В зависимости от пользовательских настроек, Vim может защитить вас от четырех возможных причин потери данных:

  1. Сбой во время редактирования (между сохранениями). Vim может защитить от этого, периодически сохраняя вносимые изменения в файле подкачки.
  2. Защита от редактирования одного и того же файла двумя экземплярами Vim, защита от перезаписи изменений, внесенных через один или несколько экземпляров. Это тоже делается через файл подкачки.
  3. Сбой во время самого процесса сохранения после изменения конечного файла, но до полной записи нового содержимого. Vim может защитить вас от этого с помощью функции «writebackup». Для этого он создает в процессе сохранения новый файл, которым впоследствии заменяет оригинал, если все прошло гладко. Способ замены определяется настройкой «backupcopy».
  4. Сохранение нового содержимого файла при условии восстановления оригинала. Vim позволяет сохранить резервную копию файла после внесения изменений.

Но прежде чем заняться изучением этих умных настроек, как насчет пары шуток? Вот несколько примеров комментариев из файлов vimrc на GitHub:

Управляйте всем через контроль версий».
«Резервные копии для ссыкунов. «Не создавайте файл подкачки. Только хардкор!»
«Мы живем в мире контроля версий, поэтому свопам и резервным копиям место на помойке».
«Зачем вам файлы резервных копий, если достаточно контроля версий».
«Я никогда не пользовался файлами резервных копий Vim… Пользуйтесь контролем версий».
«Большинство вещей можно найти с помощью контроля версий».
«Отключите резервное копирование файлов, ведь вы все равно пользуетесь системой контроля версий ;)».
«И пришел контроль версий, и Git спас нас».
«Отключите файлы подкачки и систему резервного копирования. Используйте контроль версий».
«Только контроль версий! ВСЕГДА!»
«Мне не нужно резервное копирование, ведь я работаю с контролем версий». Всегда используйте контроль версий!

Если вы откажетесь от файла подкачки и резервного копирования, вы лишитесь защиты в случая, описанных в пунктах №1 и №2. Ирония в том, что комменты выше отражают лишь понимание четвертого и, частично, третьего типа сбоя.

Вот пример конфигурации, которую я рекомендую для обеспечения безопасной работы:

" Protect changes between writes. Default values of " updatecount (200 keystrokes) and updatetime " (4 seconds) are fine
set swapfile
set directory^=~/.vim/swap// " protect against crash-during-write
set writebackup " but do not persist backup after successful write
set nobackup " use rename-and-write-new method whenever safe
set backupcopy=auto " patch required to honor double slash at end
if has("patch-8.1.0251") " consolidate the writebackups -- not a big " deal either way, since they usually get deleted set backupdir^=~/.vim/backup//
end " persist the undo tree for each file
set undofile
set undodir^=~/.vim/undo//

Эти настройки включают резервное копирование для незавершенной записи, но не сохраняют файлы после успешного окончания операции, потому что у нас же есть контроль версий, самый лучший контроль версий, бла-бла-бла и т.д. и т.п. Обратите внимание на то, что вам может понадобиться mkdir ~ / .vim / {swap, undodir, backup}, иначе Vim будет обращаться к следующей доступной для чтения папке. Также, вероятно, нужно будет выполнить команду chmod для целевых папок, чтобы их содержимое было приватным, поскольку файлы подкачки и история бэкапов могут содержать конфиденциальную информацию.

Такое написание позволяет функции устранять возможную неоднозначность в путях файлов подкачки и резервных копий для файлов с одинаковыми именами, которые при этом находятся в разных каталогах. Стоит отметить, что особенность путей нашего конфига заключаются в том, что закрываются они всегда слэшем. В недавнем патче Vim была ошибка, из-за которой слэш не учитывался для backupdir, так что защита от нее показана выше. Например, файл подкачки для / foo / bar будет сохранен в ~ / .vim / swap /% foo% bar.swp (слэши я экранировал знаками процента).

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

Это означает, что вы можете внести изменение, откатить его, а потом повторить те же изменения вновь, и все это будет тремя разными точками восстановления. Когда мы говорим об откатах, то стоит помнить о том, что Vim поддерживает полное древо истории редактирования файлов. С помощью этой команды вы можете перемещаться между конкретными изменениями или разными версиями в зависимости от времени: прыгать с шагом в 5 минут, или опираться на количество сохраненных файлов. Время и объем внесенных изменений можно проверить с помощью команды undolist, но именно древо вытащить из нее проблематично. При этом на мой взгляд, навигация по каталогу откатов с помощью плагина — хороший вариант, но undotree — вариант железобетонный.

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

Также вам может потребоваться использование установки nowritebackup, если вы работаете с огромным по объему файлом, а дисковое пространство у вас ограничено. Ну и несколько финальных оговорок: следите за всеми файлами резервного восстановления, они могут накапливаться в папке ,vim и со временем начнут отжирать солидный объем дискового пространства. По умолчанию параметр backupskip отключает резервное копирование файла во временном системном каталоге. Об этом моменте стоит помнить, потому что Vim попытается сделать полную копию вашего файла, что приведет к очевидным последствиям.

Вы можете использовать его в каталогах, в которых нет контроля версий. Еще «patchmode» Vim напрямую связан с механизмом резервного копирования. Запустите set patchmod = .orig и любой foo-файл будет скопирован и перезаписан в foo.orig. Например, когда вы хотите загрузить tar-архив, внесите изменения и отправьте патч по списку рассылки, не добавляя его в git.

Include и path

Большинство языков программирования позволяют включать (include) один модуль или файл в другой. Vim умеет отслеживать идентификаторы через path, include, suffixesadd, и includeexpr. Поиск по индентификатору (см. help include-search) — это альтернатива мониторингу файлов по тегам ctags для системных заголовков.

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

Также при использовании gf на имени файла Vim ищет путь перехода к нему. Если все работает правильно, вы можете нажать [i на идентификаторе, чтобы получить его описание, либо же нажать [d для получения макропостоянной переменной. Последнее замедляет поиск по идентификатору и каталогам, т.к. Поскольку путь влияет и на команду :find, некоторые пользователи имеют привычку добавлять **/* или другие общедоступные каталоги к имени пути для того, чтобы использовать нечеткий поиск. просматривается и то, что не имеет отношения к нашей задаче.

Суть заключается в нажатии (обычно это пробел с обратным косым слэшем) и вводе имени файла с использованием табуляции или CTRL-D. Есть способ получить тот же эффект нечеткого поиска, не загрязняя при этом сам путь. Это поможет найти файл.

" fuzzy-find lite
nmap <Leader><space> :e ./**/

И опять повторюсь: параметр path был разработан для верхних (headers) файлов. Если вам нужны еще пруфы, есть целая команда: checkpath, которая показывает, работает ли путь. Загрузите любой файл из C и запустите checkpath. Он вернет вам дамп файлов, которые он не смог найти, но которые были включены в текущий файл. Также стоит помнить, что checkpath принудительно сбрасывает всю иерархическую цепочку файлов, зацепленных за текущий.

Он означает, что наша рабочая директория — это /usr/include, а все файлы являются родственными для активного буфера. По умолчанию путь имеет вид «., / Usr / include ,,». Спецификации директорий и глобов достаточно мощная штука, посмотрите подробнее в мануале :help file-searching.

Пример: ./src/include или ./include. В моем ftplugin для Си (подробнее расскажу позже) также есть поиск пути для файлов, включенных в текущий проект.

setlocal path=.,,*/include/**3,./*/include/**3
setlocal path+=/usr/include

Конструкция вида «**3» — это ограничитель глубины поиска по каталогам. В этом конкретном случае, глубина ограничена тремя подкаталогами. Нужно это, что избежать блокировки поиска по идентификатору.

Но, конечно, все зависит от ваших настроек и системы. Ниже вы увидите другие шаблоны, в которые можете добавить свой путь в случае, если :checkpath говорит, что файлы не могут быть найдены.

Также посмотрите команды: :he [, :he gf, :he :find.

Конец первой части.

Теги
Показать больше

Похожие статьи

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть