Андрей Попов Заметки, переводы, ссылки на ресурсы

Большая идея vim


перевод статьи mike kozlowski “why atom can’t replace vim”

Изучение уроков редактора vi

1976 был хорошим годом для текстовых редакторов. Ричард Столлман и Гай Стил написали первую версию Emacs. Билли Джой в Беркли написал vi (хотя еще несколько лет спустя он так не назывался).

В первом приближении можно сказать, что каждый из этих двх редакторов построен вокруг определенной большой идеи. Глядя на популярные современные редакторы типа Sublime Text и Atom, можно с уверенностью сказать, что большая идея Emacs была понята и хорошо изучена, а вот идея Vim’а — нет.

Emacs и расширяемость

Главная идея Emacs заключалась в том, чтобы его можно было легко модифицировать и расширять. Функциональность редактора определяется библиотекой команд, которые привязываются к определенным клавиатурным комбинациям. Например, команде save-buffer соответствует комбинация клавиш <C-x><C-s>, команде kill-region комбинация <C-w> и так далее.

Если эти клавиатурные комбинации вам не подходят, их можно поменять — например, привязать к команде kill-region комбинацию <C-k>. Более того, можно не только назначать нажатия клавиш существующим командам, но и писать собственные функции на том же языке, на котором написаны встроенные функции редактора (в случае GNU Emacs это язык Lisp). Пользовательский интерфейс редакторов чрезвычайно гибок, его можно изменять под свои потребности.

Это звучит немного банально, вроде бы мы сейчас говорим об очевидных вещах, но эта очевидность связана с тем, что большая идея Emacs распространилась очень широко и сегодня расширяемость является стандартной возможностью любого серьезного редактора. В Sublime Text вместо Lisp используется Python, в Atom — язык Coffeescript, но базовые команды и клавиатурные комбинации встроены в ядро редактора. Даже Vim перенял расширяемость от Emacs: скрипт Vim может определить новые функции, которые можно связывать с клавиатурными комбинациями.

Vi и компонуемость

Большая идея Vi не получила столь большого распространения и влияния.

Редактор Vi базируется на компонуемости команд (command composability). Здесь предпочтение отдано маленьким командам общего назначения, которые можно комбинировать с объектами для составления более крупных команд. В отличие от такого подхода Vim, Emacs и его идейные потомки (включая Sublime Text и Atom) используют монолитные команды специального назначения.

Рассмотрим пример. Пусть вы хотите переместить курсор на следующее слово, к концу строки, к концу файла или к концу абзаца.

В Emacs имеются команды для этих перемещений: forward-word, move-end-of-line, end-of-buffer и forward-paragraph соответственно. В Atom есть команды для трех таких перемещений: moveCursorToBeginningOfNextWord(), moveCursorToEndOfLine() и moveCursorToBottom().

В Vim также определены команды для перемещений: w, $, G, }. Такие странные имена функций — наследие непрограммируемого прошлого Vi, когда клавиши и команды были неразрывно связаны друг с другом. Однако пока концептуально ничего необычного в Vim мы не видим.

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

В арсенале Emacs имеются только две из этих функций: kill-word и kill-line. В Atom реализованы аналогичные функции deleteToEndOfWord() и deleteLine().

В Vim ситуация обстоит иначе. В Vim есть только одна команда: d, что означает “delete” (удалить). Что именно будет удалено при вызове такой команды? Это мы сами явно указываем при вызове команды удаления. Команда d комбинируется с командами для перемещения: dw удалит следующее слово, d$ — удалит текст до конца текущей строки, dG — до конца файла и d} — до конца абзаца.

Именно эта компонуемость команд определяет мощь Vim. В Emacs и Atom нет команд для удаления текста до конца файла или абзаца — даже несмотря на то, что в этих редакторах имеются команды для перемещения коурсора в эти позиции. А в Vim, если вы можете переместить курсор куда-то, то вы сможете и удалить текст от текущего положения курсора до этого места.

Кроме того, компонуемые команды лучше согласованы, их проще запоминать. Например, команда для копирвания текста в Vim называется y. Вы знаете, как скопировать текст до конца строки/файла/абзаца? Конечно же, знаете: y$, yG и y} соответственно. Команда, увеличивающая отступ, называется > и вы уже знаете, что делают команды >$, >G и >}. Преобразование к нижнему регистру осуществляется командной gu, поэтому понятно, что делают команды gu$, guG и gu}.

Естественно, это работает и в другую сторону. Если вы узнали, что команда t= означает “переместить курсор к следующему вхождению символа =”, то вы теперь знаете, к чему приведет выполнение команд dt=, yt=, >t= и gut=. Компонуемость команд Vim означает, что каждая команда, которую вы узнали, может действовать на любую “цель”, поэтому каждое новое перемещение или объект, о котором вы узнаете, делает каждую команду Vim более мощной и функциональной.

Эта философия минималистичных команд, которые можно компоновать друг с другом, лежит в основе оригинальной философии Unix, и Vim в полной мере следует ей, как никакой другой текстовый редактор.

Vim навсегда?

Да, конечно, Vim несовершенен:

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

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


Похожие посты

Вперед Шпаргалка Vim

Содержание