tech-tips/Программное обеспечение/Текстовые редакторы/vi, vim/Почему, ну почему, эти придурки используют vi.md

41 KiB
Raw Blame History

source
https://habr.com/ru/post/307084

Предлагаю читателям "Хабрахабра" перевод статьи "Why, oh WHY, do those #?@! nutheads use vi?" за авторством John Beltran de Heredia.

Да, даже если вы не можете в это поверить, у редактора #vi, увидевшего свет более тридцати лет назад (и его более молодого, всего-то пятнадцатилетнего лучшего клона & большого улучшения — #vim) очень много фанатов.

Нет, они не динозавры, которые не хотят идти в ногу со временем — сообщество пользователей vi продолжает увеличиваться: я, который начал только два года назад (после десяти лет работы программистом). Мои друзья переходят на vi сейчас. Черт, большинство пользователей vi даже еще не были рождены, когда он был написан!

Да, есть конкретные причины, почему модель редактирования vi/vim превосходит любую другую. Вам не надо быть экспертом в Unix, чтобы использовать vi — он доступен бесплатно практически для любой существующей платформы; для большинства IDE существуют плагины, позволяющие использовать его возможности. Давайте же развеем некоторые заблуждения и рассмотрим пару примеров, демонстрирующих его превосходство.

Заблуждение №1: модальное редактирование

Впервые столкнувшись с vi или vim, вы испытываете шок и отвращение от того что должны нажать "i" для того, чтобы начать вводить текст. Вы не можете вспомнить, какая из кнопок "hjkjl" за какое направление отвечает. И надо нажимать "a", чтобы печатать в самом конце строки. Так как вы, вероятно, уже использовали другие редакторы, а в режиме ввода работает навигация стрелочками, вы используете только его, переходя в командный режим только в случае крайней необходимости. Возможно, вы потратите на это минут двадцать, постоянно жалуясь "как, во имя всего святого, я должен запомнить в каком режиме сейчас редактор!" — и никогда не захотите воспользоваться vi снова.

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

Позвольте мне объяснить философию, лежащую за этим.

Команды в vi задуманы комбинируемыми: 'd' значит "удалить", 'e' значит "переместить курсор в конец слова", поэтому 'de' завершенная команда, означающая "удалить все от текущего положения курсора до следующего конца слова" (что-то вроде Ctrl-Shift-Right, Left, Del в большинстве обычных редакторов).

Первым положительным следствием из этого является то, что команда '.' повторяет последнюю законченную комбинированную команду редактирования (но не команду перемещения). После нажатия 'dw', '.' ведет себя как команда "удалить от текущего положения курсора до следующего начала слова". Вы можете перемещаться по файлу со всей мощью команд навигации и нажимать '.' везде, где нужно удалить все до начала следующего слова, очень быстро. Эта возможность является невероятно мощной.

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

Это значит, что если вы напечатали "iHello[ESC]", что вводит "Hello" в текущей позиции курсора, то теперь '.' — это команда, которая вводит "Hello" в текущей позиции курсора. И все на этом. Вы можете себе представить, на сколько это мощная возможность. "A" переводит курсор в конец строки и активирует режим ввода. После завершения набора нажатием [ESC] вы можете нажать '.' где угодно, чтобы повторить ввод в конце строки.

Еще один даже более впечатляющий пример: команда 'ce', являющая комбинацией команд 'c' и 'e'. Команда 'c'hange удаляет диапазон, обозначенный следующей за ней командой перемещения и активирует режим ввода. Как команда 'd', но с выходом из командного режима. Плюс в том, что текст, набранный в течении следующей (короткой) сессии ввода, тоже является частью команды. Так что если вы наберете 'ceHello[ESC]', вы замените часть слова от текущего положения курсора до конца слова на "Hello", а после этого команда '.' позволит вам повторить этот ввод столько раз, сколько понадобится.

Команды перемещения тоже могу быть гораздо более сложными и дополняться разнообразными командами-редактирования-переводящими-в-режим-ввода ('o' — 'создать новую строку под текущей', 'O' — 'создать строку над текущей', 'S' — 'удалить все до конца строки' и т.д. все они переводят в режим ввода ). Только представьте, какие паттерны редактирования вы можете создавать и повторять с помощью простого нажатия '.'!

Пример №1: потрясающая команда "точка"

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

!ymmyepg45gpx39qjnub_eudslyw.gif

Весь код начинается с этого, не так ли? Теперь было бы неплохо удалить символы точки с запятой и добавить пустые тела функций. С курсором находящимся в положении как на картинке выше вы можете нажать "A" чтобы перейти прямо к вводу в конце строки:

!-n_d9r36gihoipiuutskdcfos1q.gif

Обратите внимание на курсор режима ввода в конце строки. Теперь вам надо удалить ";" с помощью [BACKSPACE] и набрать "[ENTER] { [ENTER] } [ENTER]", чтобы создать пустое тело функции, как в любом другом текстовом редакторе.

!xghffolhugsvkflrrh34pioce8g.gif

Теперь жмём эскейп, чтобы выйти в командный режим:

!zfysxzhyo9btig_wnj_5cus1blw.gif

А теперь надо все это повторить с оставшимися двумя. Как это сделать? Легко: нажимаем 'j' чтобы переместить курсор на строку вниз и затем '.', чтобы повторить редактирование (от нажатия "А" до [ESC]). Если вы нажмете 'j.j.', то получите следующее:

!vqiukldg3me0j1ocv8gh7oyzitc.gif

Просто 'j.j.'! Ключом здесь является архитектура команд vi вместе с тем, что [BACKSPACE] является частью редактирования как обычный набор текста и тем, что операции редактирования обладают высокой повторяемостью. Подумайте, сколько ваших ежедневных правок являются повторяемыми? Ага, я так и думал.

Заблуждение №2: дело не в регулярных выражениях

Vi/Vim прекрасно справляются с обработкой регулярных выражений. Все более-менее серьезные текстовые редакторы поддерживают регулярные выражения — поиск, замену и так далее, но только vi (из тех что я знаю) может использовать их сложные комбинации вроде "поиска и замены второго включения "begin" после строки содержащей "proc", или что там еще может придти вам в голову.

Так что я не хочу принизить значение регулярных выражений или способность vi/vim их обрабатывать. Но настоящая сила vi, сила, без которой вы не сможете жить после того, как научитесь ее использовать — это сила базовой модели редактирования текста:

  • Одно- или двухкнопочные команды для перемещения именно туда куда вам надо в строке или на экране.
  • Команды вроде 'd' или 'c' которые будучи скомбинированы с командами перемещения позволяют напрямую изменять интересующий вас кусок кода с возможностью повторения редактирования простым нажатием '.'
  • Руки всегда в удобном положении на клавиатуре. Редактирование одинаково комфортно и на ПК и на ноутбуке.

Пример №2: умные диапазоны

Давайте рассмотрим следующий типичный пример. Это просто вызов функции встроенный в некое сложное выражение:

!1otrsmihnkbibpu2lbwdmsl7viq.gif

Как вы можете видеть, курсор находится в начале вызова функции. А теперь представьте, что мы хотим убрать его оттуда и назначить некоторой локальной переменной. Для начала нам надо выделить вызов функции, скопировать и удалить его, напечатать имя переменной, переместиться на строку вверх для объявления этой переменной. Следуя обычной модели редактирования вы бы начали играться с Ctrl-Right и left/right пока не сделали бы все как надо. Но не с vi/vim. Команда перемещения '%' позволяет перемещаться от открывающей скобки (или другого группирующего символа) до соответствующей закрывающей скобки — но если курсор не находится на одном из этих специальных символов, vim идет вправо до первого такого символа, а затем перемещает курсор на соответствующий ему закрывающий. То есть, в нашем случае, курсор переместиться прямо на закрывающую скобку вызова функции!

Зная, что команда 'c' удаляет текст на всей протяженности следующего за ней перемещения (а так же копирует его в буфер обмена), мы можем просто набрать 'c%' и получить следующее:

Наш вызов функции скопирован в буфер обмена и мы готовы ввести имя переменой. Неплохо для двух кнопок! После ввода имени переменной и нажатия [ESC]:

Теперь в командном режиме мы можем нажать 'O' для создания строки над текущей и перехода в режим ввода, а затем объявить переменную:

!4mv7tpdn6zezujq_-r9acd_bki4.gif

Теперь нам надо вставить вызов функции, а так как он уже в буфере обмена мы можем вставить его нажав Ctrl-R, а затем " (немного не интуитивно, но это комбинация для вставки из стандартного буфера обмена ), дальше ";" и [ESC]:

!78a2bi6j2yglxklqhdbsrgsbuv4.gif

Заблуждение №3: надо быть психом и/или гением чтобы использовать это

Ну что же, я надеюсь, что благодаря объяснениям и примерам выше у вас появилось понимание потенциала возможностей, предоставляемых vi/vim. Тяжело в учении (см. ниже), но если вы собираетесь кодить восемь часов или больше в день годами, то это вторая наилучшая инвестиция после "слепой печати" (которую вы уже освоили, не так ли? Если нет, начните с нее). Потратив несколько недель сейчас, вы будете получать дивиденды всю свою жизнь.

Смысл в том, что с vi ваша клавиатура превращается в специализированный геймпад для редактирования текста с практически сотней кнопок, каждая из которых имеет как минимум две функции — с шифтом и без шифта; таким образом, у вас уже под две сотни функций доступных по нажатию одной кнопки (не считая шифта) (прим. пер.: что-то много автор насчитал, можно смело на два делить). Мощные сами по себе команды можно комбинировать друг с другом для получения наилучшего результата. Во время ввода это стандартная клавиатура, но при возврате в командный режим это идеальная машина для редактирования текста

Пример №3: манипуляции с разграниченными блоками

Еще один простой пример. Работает только в vim, так как использует одну из специфичных для него команд перемещения. Скажем, вы находитесь внутри блока ограниченного угловыми скобками, что не редкость в наши дни XML:

Как выделить текст внутри чтобы копировать/изменить/удалить его? В обычных текстовых редакторах вы вынуждены убрать руки из текущего комфортабельного положения и воспользоваться стрелками, или того хуже мышью. Любой из этих вариантов не удобен, особенно на ноутбуке. Как сделать это в vim? Вы просто используете одну из команд перемещения по объектам текста, каждая из которых начинается с 'i' или 'a' (эти символы так же используются как команды редактирования и поэтому могут следовать только после 'd' или 'c' команд) 'i>' означает текущий блок ограниченный угловыми скобками, где 'i"' от 'inner'. Так что вы можете набрать 'di>' чтобы удалить весь текст внутри угловых скобок:

Вы можете использовать '(' или ')' чтобы выделить текущих блок ограниченный скобками (или даже 'b' от 'block'), '{' или '}', '[' или ']', 'w' для пунктуационно выделенного слова, или 'W' для слова выделенного пробелами, предшествующее 'i' c любым из них для внутреннего содержания, или 'a' чтобы выделить разделители тоже.

Заблуждение №3: надо быть психом и/или гением чтобы использовать это

Ну что же, я надеюсь, что благодаря объяснениям и примерам выше у вас появилось понимание потенциала возможностей, предоставляемых vi/vim. Тяжело в учении (см. ниже), но если вы собираетесь кодить восемь часов или больше в день годами, то это вторая наилучшая инвестиция после "слепой печати" (которую вы уже освоили, не так ли? Если нет, начните с нее). Потратив несколько недель сейчас, вы будете получать дивиденды всю свою жизнь.

Смысл в том, что с vi ваша клавиатура превращается в специализированный геймпад для редактирования текста с практически сотней кнопок, каждая из которых имеет как минимум две функции — с шифтом и без шифта; таким образом, у вас уже под две сотни функций доступных по нажатию одной кнопки (не считая шифта) (прим. пер.: что-то много автор насчитал, можно смело на два делить). Мощные сами по себе команды можно комбинировать друг с другом для получения наилучшего результата. Во время ввода это стандартная клавиатура, но при возврате в командный режим это идеальная машина для редактирования текста

Пример №3: манипуляции с разграниченными блоками

Еще один простой пример. Работает только в vim, так как использует одну из специфичных для него команд перемещения. Скажем, вы находитесь внутри блока ограниченного угловыми скобками, что не редкость в наши дни XML:

Как выделить текст внутри чтобы копировать/изменить/удалить его? В обычных текстовых редакторах вы вынуждены убрать руки из текущего комфортабельного положения и воспользоваться стрелками, или того хуже мышью. Любой из этих вариантов не удобен, особенно на ноутбуке. Как сделать это в vim? Вы просто используете одну из команд перемещения по объектам текста, каждая из которых начинается с 'i' или 'a' (эти символы так же используются как команды редактирования и поэтому могут следовать только после 'd' или 'c' команд) 'i>' означает текущий блок ограниченный угловыми скобками, где 'i"' от 'inner'. Так что вы можете набрать 'di>' чтобы удалить весь текст внутри угловых скобок:

Вы можете использовать '(' или ')' чтобы выделить текущих блок ограниченный скобками (или даже 'b' от 'block'), '{' или '}', '[' или ']', 'w' для пунктуационно выделенного слова, или 'W' для слова выделенного пробелами, предшествующее 'i' c любым из них для внутреннего содержания, или 'a' чтобы выделить разделители тоже.

Заблуждение №4: "hjkl" для перемещения по тексту?

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

В любом случае, хотя по началу вы будете использовать hjkl для перемещения по тексту, освоив vi/vim вы, вероятнее всего, откажетесь от использования клавиш 'h' и 'l'. Почему? Потому что есть гораздо более мощные команды, которые могут переместить курсор в нужное место текста намного быстрее. Я обнаружил, что при редактировании строки всегда есть команда перемещения, которая перенесет меня прямо к нужному символу, я использую эти: 'f' дополняемая любым символом следующее вхождение которого я хочу найти, '%' для перемещения по скобкам и т.д. При навигации по файлу вы можете использовать команды чтобы перейти вверх/середину/низ экрана напрямую, '/' для быстрого поиска, ']]' и родственные ей для навигации по функциям, и т.д.

Пример №4: приятные команды

Некоторые команды настолько удобные, что вы можете забыть о том, что используете их. 'H', 'M' и "L" перемещают курсор на верхнюю, среднюю и нижнюю линии экрана соответственно. 'zt', 'zz', 'zb' не перемещают курсор, но скролят текст так, чтобы курсор оказался вверху, в середине, либо в низу экрана. '*' ищет следующее появление слова, на котором находится курсор вперед по тексту, '#' делает тоже самое назад. И таких команд еще много...

Заблуждение №5: так как мы думаем над проблемой 90% времени, а программируем решение всего 10%, прокачивать скорость редактирования практически бесполезно.

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

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

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

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

Комфортность редактирования позволяет вам оставаться "в потоке" — состоянии максимальной концентрации и продуктивности. Мастерски овладев редактором текста, вы переместите редактирование на бессознательный уровень, освободив вычислительные мощности мозга для других задач. Общепринятый стиль отвлекает вас, вы используете Ctrl-Right, Ctrl-Right, Ctrl-Right, Ctrl-Right, Ctrl-Right, чтобы добраться до нужного места в коде, берете в руки мышь, чтобы выбрать опцию меню, нажимаете "принять" в диалоге подтверждения. Vi/vim же позволяет обойтись удивительно малым количеством клавиш, чтобы сделать именно то, что вы хотите.

Другие пользователи vi говорят то же самое, так что я не одинок в своих чувствах: как только вы достигаете мастерства в использовании vi, бывают такие моменты, когда после 30 секундного "взрывного" редактирования вы как-будто "просыпаетесь" и осознаете, что слышали клацанье клавиш где-то в затылочной части черепа, пока нарезали, изменяли и перемещали блоки текста. И такие моменты дают потрясающее ощущение силы.

Пример №5: выравнивание блоков

Vi и vim знают, что у вашего кода есть какая-то структура. Многие команды отражают это. Возьмем, к примеру, 'aB', которая была описана выше — она выделяет текущий ограниченый фигурными скобками блок вместе со скобками ('a}' делает то же самое) и объединим с командой '>', которая выравнивает область обозначенную следующей за ней командой перемещения. Представьте себе такой код:

!bidseyv2nnawjazqgwns4_48ore.gif

Как часто вам встречается такая задача? Да, вы конечно можете вставлять с авто-выравниванием (']p' в vim), но вдруг вы забыли, или получили такой код не копипастом, а потому что удалили кусок кода выше. В общем, вам просто надо его выровнять. В других редакторах вы перемещаете курсор, нажимаете [Tab] или сочетание клавиш для авто-выравнивания. Но не в vim, просто три клавиши '>aB' "выровнять блок" и вы получаете это:

!hcayo5vxwjp2z_ipawazhtk_w84.gif

Круто, не так ли? Никаких метаний с курсором и выделением текста, просто говорите, что именно вам нужно и vim все делает. Я считаю, что это тот тип редактирования, который дает вам настоящую власть над кодом и позволяет оставаться "в потоке".

Заблуждение №6: это просто привязанность к исчезающему прошлому

Vi уже тридцать лет*, а он до сих пор популярен. Vim — полный клон vi, в котором больше улучшений, чем в vi возможностей, жив и здравствует уже в течении 15 лет* и распространяется бесплатно почти под любую существующую платформу. Люди, которым нравится vi, находят способы использовать его везде: существуют плагины, позволяющие использовать возможности vi в Eclipse, разных приложениях для Mac, в IntelliJ IDEA, даже в emacs не один, а целых несколько встроенных эмуляторов vi (когда я кодил на лиспе в емакс, я начинал с попыток использовать его сочетания клавиш, но всегда в конечном счете заканчивал на "M-x viper-mode"), я разрабатываю и продаю ViEmu семейство плагинов для внедрения эмуляции vi/vim в Visual Studio, SQL Server, Word and Outlook, Пол Грэм ( здесь о нём на Хабре) по прежнему использует vi для разработки lisp и arc, Tim O'Reilly открытый vi-мер, SlickEdit и Crisp могут эмулировать vi...

Конечно сообщество vi не очень большое: большинство пользователей компьютера даже не освоили слепую печать, а vi добавляет еще крутизны кривой обучения. Тем не менее, те из нас, кто видел свет, никогда не вернутся к другим, менее функциональным системам редактирования так что vi/vim гарантировано еще много лет благоденствия. На самом деле, использование модели редактирования vi/vim обеспечивает вас уверенностью, что вы сможете пользоваться привычными командами независимо от того, в какой среде находитесь, от старых Unix-систем до новейших популярных IDE.

оригинальная статья опубликована 16.05.2007

Пример №6: визуальная природа

И как последний пример, чтобы вам не казалось, что vi — это только загадочные нечитаемые команды, рассмотрим некоторые более наглядные возможности (вообще это возможности уже vim, а не vi) Одна из них: при включенной подсветке поиска (выключена по умолчанию, но обычно всегда включается командой ":set hlsearch") когда вы ищите подстроку, все ее включения подсвечиваются. К примеру у вас есть такой html код:

!djllewdpe0g1z0nv20i-bm1gt3s.gif

Если вы нажмете '*', будет произведен поиск по слову, на котором находится курсор ('div'), и в результате мы получим:

!ogt0ps27cm92rp0twhqzi0khos8.gif

Как вы видите, курсор переместился и все включения подсвечены.

Давайте рассмотрим кое что еще. Мы уже видели команды вроде 'd', или 'c', которые действуют на область в соответствии со следующей командой. Но если мы хотим сделать процесс более наглядным, мы можем использовать визуальный режим: нажмите 'v', передвиньте курсор и вы увидите, что его начальное положение подсвечено, затем наберите команду, чтобы увидеть результат. Команды поиска работают здесь точно так же. Если вы нажмете 'V' вместо 'v', то выделяться будут целые строки. Нажмите 'V', а затем 'k'(вверх) после этого:

!qxr7h7ydj8rdjz0rekamenwdsvw.gif

Как вы видите, две строки подсвечены как выделенные. Скажем, вы хотите продолжить выделение до открывающего 'div' (он подсвечен желтым). Нажмите 'N' (предыдущее совпадение) и получите это:

!wxfbh0ao3dskpc6xbfjsttp1tvq.gif

Теперь мы можем сделать все, что придет в голову, например, набрать 'gU', чтобы перевести весь текст в верхний регистр (и вернуться в командный режим):

!ht5gzfslhbuwc8abu_sanohrxxy.gif

Ну а теперь давайте поговорим о правильной "обобщенной концепции" vi/vim.

Правильная концепция №1: крутая кривая обучения

Это факт, что научиться эффективно использовать vi/vim непросто. Придется потратить от нескольких недель до нескольких месяцев и первый опыт не будет приятным. Мне кажется, это главная причина, почему модель редактирования vi непопулярна и никогда не станет популярной. Вам надо перевести, выучить и отработать около 30 команд, прежде чем вы начнете выигрывать в скорости у пользователей других редакторов. Хотя в большинстве случаев это однокнопочные команды (почти все имеют простые мнемоники, облегчающие запоминание), это все равно непростая задача. Очень легко сдаться и вернуться в привычный редактор. Но я не знаю никого, кто выполнив эти условия, вернулся бы к старым привычкам.

Заключение

Делайте, что хотите. Не учитесь пользоваться vi/vim, если считаете, что это требует слишком много усилий и не окупится. Изучите emacs вместо vi. Или продолжайте использовать никудышный редактор кода своей IDE. Но, в любом случае, никогда больше не заявляйте, что пользователи vi придурки. Я надеюсь, что преуспел в объяснении, почему он им (нам) так нравится и вы должны были, по крайней мере, оценить его мощь, даже если и не хотите его использовать.

Если вы захотите поближе познакомится с vi, вот несколько полезных ссылок: