Введение в POSIX'ивизм

       

Vi и Vim: введение в тему


Редактор vi (или какой-либо из его клонов) - непременный атрибут всех Unix-систем, и потому любой их пользователь должен иметь о нем представление, хотя для повседневной работы какой-либо иной редактор может оказаться более подходящим.

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

Существует несколько редакторов, основанных на vi, включающих дополнительные возможности, но полностью совместимых с ним по системе базовых команд. И потому знание vi обеспечит возможность работы с любым из его клонов. Более того, если в некоей Unix-системе вместо vi используется какой-либо из редакторов-клонов, например, Vim или elvis, в каталоге /usr/bin

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

$ vi имя_файла

хотя реально при этом запускается, например, Vim. Тем более, что сам по себе vi в свободных POSIX-системах не используется из-за лицензионных соображений. Так что далее термины vi и Vim используются как синонимы, но везде имеется в виду Vim (Vi Improved).

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

$ vim ~/mytext/newtext.txt

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


Команда vim без имени файла откроет редактор Vim и выведет заставку следующего содержания:

VIM - Vi IMproved ~ ~ version 6.1b BETA ~ by Bram Moolenaar et al. ~ Vim is open source and freely distributable ~ ~ Help poor children in Uganda! ~ type :help iccf for information ~ ~ type :q to exit ~ type :help or for on-line help ~ type :help version6 for version info

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



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

В vi существует три принципиально различных режима работы - командный, или визуальный (visual command mode), именуемый также нормальным, режим ввода (edit mode) и т.н. ex-режим, или режим построчного редактирования (ex mode или colon mode), который по-русски именуется еще и режимом ввода команд. Кроме того, в Vim (но не в классическом vi) дополнительно выделяется еще режим визуального выделения, или выбора.

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

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


В нормальном режиме нажатия клавиш не приводят к вводу символов, а интерпретируются как внутренние команды навигации и редактирования, привязанные к различным алфавитно-цифровых или символьным клавишам и их комбинациям. Например, нажатие клавиши h вызывает перемещение курсора на один символ влево, клавиши l - на один символ вправо, k - на строку вверх, j - на строку вниз, и т.д.).

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

Естественно, создание текста в командном режиме невозможно. Для этого следует перейти во второй режим (будем называть его режимом ввода), для чего служат разнообразные команды (нормального режима!), например, a (от append) и i (от insert). Здесь нажатия клавиш приводят к вводу обычных буквенно-цифровых символов (после текущей позиции курсора в случае первой команды и перед ней - в случае второй), позволяя создавать новый текст или редактировать имеющийся. Хотя последнее более эффективно в командном режиме, возврат в который осуществляется клавишей Escape.

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

  • открытие существующего файла (:edit имя_файла, здесь и далее символ : указывает на принадлежность команды к командному режиму); если какой-либо файл перед этим уже загружен, он будет закрыт и замещен новым; если же изменения в нем не были сохранены - последует сообщение об ошибке;




  • вставка существующего файла в позицию курсора (:read имя_файла);


  • запись файла (:write), в том числе под другим именем (:write имя_файла);


  • выход из редактора (:quit), происходящий, если текущий файл не изменялся или был предварительно сохранен;


  • выход из редактора с предварительным сохранением измененного файла (:xit - от exit).


  • Одна из возможных причин путаницы нормального и командного режима - то, что в последнем допустимы любые аббревиатуры указанных команд, вплоть до односимвольных (каковые в обиходе, как правило, и используются): :e для открытия файла, :r -для его вставки, :w - для записи, :q и :x - для выхода. Однако это именно сокращения команд, а не клавиши, предопределенные для неких действий, как в нормальном режиме. Возможно совмещение команд командного режима, например, :wq - выход с предварительным сохранением измененного файла (что аналогично команде :x).

    Команды отправляются на исполнение нажатием клавиши Enter, после чего происходит возврат в нормальный режим. Однако попытка, например, закрыть редактор без сохранения изменений в редактируемом документе (командой :q) или загрузить новый файл (командой :e), не сохранив предыдущий, вызовет сообщение об ошибке. Для принудительного выполнения таких действий команды :q и :e должны сопровождаться символом ! без пробела. Например, команда :q! закроет редактор vi, не сохранив изменений в текущем файле.

    Действия командного режима частично дублируются в режиме нормальном. Так, в последнем для закрытия же файла (с предварительным сохранением изменений) используется комбинация Z-Z (двойное нажатие клавиши Z - регистр важен!), что является эквивалентом сочетания команд :wq командного режима.

    Четвертый режим Vim назовем режимом выбора, поскольку именно для выбора фрагментов текста с целью последующего применения к ним команд нормального режима. Переход в него (как обычно, из нормального режима) осуществляется нажатием клавиш v или V. В обоих случаях нажатия клавиш управления курсором приводят не к его перемещению, а к выделению блока, в первом - начиная с текущего положения курсора в пределах строки, во втором - начиная с начала маркированной курсором строки.


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

    В современных версиях Vim предусмотрено нечто вроде индикации режимов - при включении режима ввода в нижней части экрана появляется надпись

    -- INSERT --

    при переходе в режим выбора - надпись

    -- VISUAL --

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

    Такая система работы может показаться запутанной начинающему пользователю. Однако она имеет глубокое внутреннее обоснование. Редактор vi создавался изначально как кросс-платформенный, который обязан работать на любых типах реальных и виртуальных терминалов. И потому все действия в нем можно осуществить, не покидая основной, алфавитно-цифровой, части клавиатуры, без обращения к дополнительным клавишам - стрелкам управления курсором, Home, End, PageUp, PageDown, Insert, Delete, Backspace.

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

    Поскольку нормальный режим vi является не только основным, но и наиболее характерным для этого редактора (и - непривычным для пользователя!), имеет смысл ознаком иться с ним подробнее. Все изобилие команд vi (а их насчитывается много десятков) можно разделить на три группы:

  • команды навигации;


  • команды редактирования;


  • команды перехода (в режим ввода).




  • Команды навигации служат для перемещения курсора по тексту. В консольном режиме для этого могут быть использованы и обычные клавиши управления курсором (стрелки, PageUp/PageDown, Home/End). Однако уже в различных программах эмуляции терминала в Иксах их поведение неоднозначно (и зависит от настроек). К тому же внутренние команды дают больше возможностей для навигации по тексту, чем клавиши стандартных клавиатур.

    Так, уже говорилось, что в vi существуют команды h и l, k и j, действие которых эквивалентно нажатиям клавиш Left и Right, Up и Down, соответственно. Но, кроме того, с помощью парных команд w и W можно переместиться вперед, соответственно, на т.н. "маленькое" слово (то есть отделенное пробелом или любым знаком препинания, символами - или +) и на "большое" (то есть обязательно отделенное пробелом) слово. Пара команд b и B выполняет аналогичное перемещение назад, а команды e и E перемещают курсор в конец следующего "маленького" и "большого" слова.

    Вообще, для многих команд vi характерно наличие парных эквивалентов - в нижнем и верхнем регистрах одной клавиши (w и W, e и E); действие второй команды из пары как бы расширяет действие первой.

    Возможны также перемещения в предыдущее (символ (, то есть открывающей скобки) и последующее (символ ), закрывающей скобки) предложения, в начало (H) и конец (L) экрана, в начало (0 - ноль) и конец ($) строки и т.д. - список навигационных команд приближается к 30. Иными словами, нажатием одной клавиши или, в крайнем случае, двухклавишной комбинации (Control+f - на следующую экранную страницы, Control+b - на предыдущую) можно переместиться в абсолютно любое заранее определенное место текущего документа.

    В дополнение к этому, команды навигации vi могут использоваться с численными аргументами. Например, команда 5h переместит курсор на 5 символов влево (считая символ в позиции курсора), а команда 3k - на три строки вверх.

    Далее, для навигации по тексту могут использоваться символы - (минус) для перемещения на одну строку вверх и + (плюс) для перемещения на одну строку вниз.


    Особенно эффективны они в сочетании с численными аргументами: командой 7+ возможно перемещение на седьмую строку вперед, а командой 13- - на тринадцатую строку назад (в обоих случаях - включая строку в позиции курсора).

    Команды редактирования предназначены для модификации существующего текста без перехода в режим ввода. Конечно, и в последнем возможно удаление и замена символов стандартными клавишами Delete или Backspace, но, как и в случае с навигацией, возможности командного режима в этом отношении много шире.

    Так, наряду с удалением единичного символа в позиции курсора (x) или перед ней (X), возможно удаление слова (dw), строки (dd) или ее части перед (dD) или после (dG) курсора, предложения (d)) или абзаца (d}).

    Как и навигационные команды, команды редактирования могут использоваться с численными аргументами. Так, команда 5dd удалит текущую строку и еще четыре строки вниз. А с помощью команды 3dw можно удалить три слова подряд (включая то, на котором находится курсор).

    Не меньше команд отвечает за копирование фрагментов, их вставку и замену. Например, команда yw копирует "маленькое" слово, yW - "большое", yy - строку, y) - предложение, y} - абзац. Командой же p удаленный или скопированный фрагмент вставляется в позицию курсора.

    Действие ошибочно введенных команд редактирования может быть отменено командой u (от undo). Вторичный ввод этой команды приведет к отмене предыдущего действия, и так далее. Для возврата ошибочно отмененной операции используется команда Control+R.

    Описание всех команд редактирования заняло бы слишком много места. Подчеркну лишь, что, как и в случае с навигацией, нажатием одной-двух клавиш можно удалить, скопировать, вставить и переместить текстовый блок практически любого размера - от единичного символа до произвольного их количества (строки, предложения, абзаца, экранной страницы).

    Команды перехода могут рассматриваться как подмножество команд редактирования нормального режима, после которых возможен ввод новых символов и их последовательностей.


    Кроме уже упомянутых a и i (ввод после курсора и в его позиции, соответственно), к ним относятся:

  • A - ввод текста в конец строки;


  • I - ввод в начало строки;


  • o - создание новой строки под текущей с возможностью ввода в нее текста;


  • O - создание новой строки над текущей, в которую также можно ввести текст.


  • Как и большинство прочих команд редактора vi, команды перехода могут использоваться с числовыми аргументами. Так, если дать команду 3a и после этого ввести некоторую последовательность символов, по выходе в командный режим (клавишей Escape) она будет повторена трижды. Аналогично, ввод текста после команды #O даст # идентичных строк.

    Редактор vi располагает средствами поиска и замены текстовых фрагментов, в том числе и с использованием регулярных выражений. Для этого предназначена команда командного режима :s (от substitute). Она дается в форме

    :#s/text1/text2/опция

    где # - количество строк, в которых операции поиска и замены должны осуществляться (без указания его действие команды распространяется только на текущую строку. Если поиск и замену необходимо выполнить по всему тексту документа, дается команда :%s.

    Следует подчеркнуть, что если не указать заменяющего текста (и опций замены), все текстовые фрагменты, указанные в качестве заменяемого текста, будут просто удалены. Во избежание этого используются опции команды :s. Так, опция /c предписывает запрос подтверждения на замену для каждого найденного фрагмента.

    И поиск, и замена в vi возможна только для последовательности символов, составляющих одну строку (то есть не содержащей символа LF). Заменяющая последовательность символов также должна образовывать единую строку.

    Описанным не исчерпываются возможности редактора vi. В частности, он (вернее, его клон Vim) поддерживает язык макрокоманд и допускает их протоколирование. В комплекте с редактором (в каталоге /usr/local/share/vim/vim###) имеется большое количество таких макросов. Там же - и детальная документация по их применению.

    Функциональность редактора Vim в значительной мере зависит от его настроек.


    Пример конфигурационного файла (vimrc_example.vim) можно обнаружить в том же каталоге (/usr/local/share/vim/vim###). Его следует скопировать в свой домашний каталог под именем ~/.vimrc и отредактировать по потребностям.

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

    set langmap=

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

    set langmap=ё,Ё~,йq, ... Б

    Правда, чтобы это сработало, Vim должен быть собран с опцией big, задаваемой в командной строке при исполнении сценария ./configure.

    А вообще редактированием файла ~/.vimrc Vim может быть адаптирован для задач любого рода, например, работы с html-документами. На сайте http://www.vim.org имеется большое количество примеров конфигурационных файлов такого рода.


    Содержание раздела