Работа с файлами

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

Чтобы редактировать файл, вы должны велеть Emacs считать его и подготовить буфер, содержащий копию текста файла. Это называется обращением к файлу. Команды редактирования применяются непосредственно к тексту в буфере, то есть к копии внутри Emacs. Ваши изменения появляются в самом файле, только когда вы сохраните буфер в файле.

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

Имена файлов

Большинство команд Emacs, которые оперируют с файлами, требуют от вас указания имени файла. (Запись и восстановление являются исключением; буферу известно, какое имя файла используется для них.) Имена файлов задаются с использованием минибуфера (смотрите раздел Минибуфер). Вы можете использовать завершение для облегчения написания длинных имён файлов. Смотрите раздел Завершение.

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

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

Например, если по умолчанию имя файла -- `/u/rms/gnu/gnu.tasks', то каталогом по умолчанию будет `u/rms/gnu/'. Если вы наберете просто `foo', не описывая каталог, то это будет сокращением для `/u/rms/gnu/foo'. `../.login' будет соответствовать `/u/rms/.login'. Если вы зададите `new/foo', это будет означать файл с именем `/u/rms/gnu/new/foo'.

Команда M-x pwd печатает каталог по умолчанию для текущего буфера, а команда M-x cd устанавливает его (значение считывается в минибуфере). Каталог по умолчанию в буфере изменяется только тогда, когда используется команда cd. Каталог по умолчанию для буфера, обращающегося к файлу, инициализируется по каталогу файла, к которому он обратился. Если буфер создаётся произвольным образом с помощью C-x b, его каталог по умолчанию копируется из того буфера, который был текущим в тот момент.

Каталог по умолчанию фактически появляется в минибуфере, когда минибуфер становится активным для чтения имени файла. Это служит двум целям: чтобы показать вам, что имеется по умолчанию, так что вы можете набрать соответствующее имя файла и с определённостью узнать, что это будет значить, и чтобы позволить вам отредактировать каталог по умолчанию и задать другой каталог. Эта подстановка каталога по умолчанию не делается, если переменная insert-default-directory установлена равной nil.

Заметим, что законно набирать полное имя файла после того, как вы войдете в минибуфер, игнорируя присутствие имени каталога по умолчанию как части текста. Окончательное содержание минибуфера может казаться неправильным, но на самом деле это не так. Например, если сначала минибуфер содержал `/usr/tmp/', и вы добавили `/x1/rms/foo', вы получите `/usr/tmp//x1/rms/foo'; но Emacs игнорирует все до того места, где встречены две косые черты подряд; в результате получается `/x1/rms/foo'. Смотрите раздел Минибуфер для имён файлов.

Литера `$' в имени файла используется для подстановки переменных среды. Например, если вы применили команду оболчки `export FOO=rms/hacks' для установки переменной среды с именем `FOO', то вы можете использовать `/u/$FOO/test.c' или `/u/${FOO}/test.c' в качестве сокращения для `/u/rms/hacks/test.c'. Имя переменной среды состоит из всех букв и цифр после `$'; или оно может быть заключено в фигурные скобки после `$'. Заметьте, что команды оболочки, которые устанавливают переменные среды, повлияют на Emacs, только если они были выполнены до запуска Emacs.

Чтобы получить доступ к файлу, содержащему в имени знак `$', напечатайте `$$'. Эта пара превращается в один `$', в то время как для одиночного `$' делается подстановка переменной. Или вы можете отменить особый смысл всех знаков в имени файла с помощью последовательности `/:' (смотрите раздел Буквальные имена файлов).

Лисповская функция, которая производит подстановку, называется substitute-in-file-name. Подстановка выполняется только для имён файлов, считываемых как таковые с использованием минибуфера.

Вы можете включать в имена файлов знаки, не входящие в ASCII, если установите переменную file-name-coding-system в отличное от nil значение. Смотрите раздел Задание системы кодирования.

Обращение к файлам

C-x C-f
Обратиться к файлу (find-file).
C-x C-r
Обратиться к файлу для просмотра, не допуская его изменения (find-file-read-only).
C-x C-v
Обратиться к другому файлу, вместо последнего посещенного (find-alternate-file).
C-x 4 f
Обратиться к файлу в другом окне (find-file-other-window). Не меняет данное окно.
C-x 5 f
Обратиться к файлу в другом фрейме (find-file-other-frame). Не изменяет то, что отображется в выбранном фрейме.
M-x find-file-literally
Обратиться к файлу без преобразования его содержимого.

Обращение к файлу означает копирование его содержимого в буфер Emacs, где вы можете его редактировать. Emаcs создаёт новый буфер для каждого файла, к которому вы обращаетесь. Мы говорим, что этот буфер обращается к файлу, для хранения которого он был создан. Emacs создаёт имя буфера из имени файла, отбрасывая каталог и сохраняя просто собственно имя. Например, файл с именем `/usr/rms/emacs.tex' получит буфер с именем `emacs.tex'. Если буфер с таким именем уже существует, то создаётся уникальное имя путем добавления `<2>', `<3>' и так далее; при этом используется наименьший номер, создающий ещё не используемое имя.

Строка режима каждого окна показывает имя буфера, который отражен в этом окне, таким образом вы всегда можете сказать, какой буфер редактируете.

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

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

Чтобы обратиться к файлу, используйте команду C-x C-f (find-file). После нее введите имя файла, который вы хотите посетить, ограниченное RET.

Имя файла считывается с использованием минибуфера (смотрите раздел Минибуфер) с использованием значений по умолчанию и завершением стандартным способом (смотрите раздел Имена файлов). Пока вы находитесь в минибуфере, вы можете прервать выполнение C-x C-f, набрав C-g.

Подтверждением того, что C-x C-f завершилась удачно, служит появление нового текста на экране и нового имени буфера в строке режима. Если указанный файл не существует и не может быть создан или считан, тогда возникает ошибка. Сообщение о ней печатается в эхо-области.

Если вы обращаетесь к файлу, который уже существует в Emacs, C-x C-f не создаёт другой копии. Она выбирает существующий буфер, содержащий этот файл. Однако, перед этим она проверяет, не изменился ли сам файл с тех пор, как вы обратились к нему или записали его в прошлый раз. Если файл был изменен, то будет напечатано предостерегающее сообщение. Смотрите раздел Защита от одновременного редактирования.

А что если вы захотите создать новый файл? Просто обратитесь к нему. Emacs печатает в эхо-области `(New File)', но в других отношениях ведет себя так же, как, если бы вы обратились бы к существующему пустому файлу. Если вы сделаете любые изменения и запишете их, то файл будет создан.

Emacs узна т из содержимого файла, какое соглашение используется в нём для разделения строк -- перевод строки (используемый в GNU/Linux и Unix), возврат каретки и перевод строки (используемые в системах Microsoft) или просто возврат каретки (используемый на Macintosh) -- и автоматически преобразует содержимое к обычному формату Emacs, в котором строки разделяются знаками перевода строки. Это часть общего средства преобразования системы кодирования (смотрите раздел Системы кодирования), и это позволяет редактировать файлы, перенесенные с различных операционных систем с одинаковым удобством. Если вы изменили текст и сохранили файл, Emacs производит обратное преобразование, заменяя переводы строки на возврат каретки и перевод строки или просто возврат каретки, если это необходимо.

Если указанный вами файл фактически является каталогом, то C-x C-f вызывает Dired, броузер каталогов Emacs, чтобы вы могли "редактировать" содержимое этого каталога (смотрите раздел Dired, редактор каталогов). Dired предоставляет удобный способ удаления, просмотра или обработки файлов в каталоге. Однако, если переменная find-file-run-dired равна nil, попытка обратиться к каталогу будет считаться ошибкой.

Если заданное вами имя файла содержит символы подстановки, Emacs обращается ко всем файлам, соответствующим этому имени. Смотрите раздел Буквальные имена файлов, если вы хотите обратиться к файлу, чье имя в самом деле содержит символы подстановки.

Если операционная система не позволяет вам изменять файл, к которому вы обращаетесь, Emacs делает буфер доступным только для чтения, так что у вас не получится внести изменения, которые будет проблематично впоследствии сохранить. Вы можете сделать буфер доступным для записи с помощью C-x C-q (vc-toggle-read-only). Смотрите раздел Разнообразные операции над буфером.

Иногда вы можете захотеть обратиться к файлу в режиме только чтения, чтобы защититься от случайного внесения изменений; делайте это, обращаясь к файлу с помощью команды C-x C-r (find-file-read-only).

Если вы обратились к несуществующему файлу неумышленно (так как вы набрали неправильное имя файла), используйте команду C-x C-v (find-alternate-file), чтобы обратиться к файлу, который вам нужен на самом деле. C-x C-v подобна C-x C-f, но уничтожает текущий буфер (после того, как сначала предложит записать его, если он изменен). При считывании нового имени файла она вставляет полное имя текущего файла, оставляя точку сразу после имени каталога; это удобно, если вы сделали небольшую ошибку, когда вводили имя файла.

Если вы обращаетесь к файлу, который существует, но не может быть прочитан, C-x C-f выдает ошибку.

C-x 4 f (find-file-other-window) похожа на C-x C-f, но буфер, содержащий описанный файл, выбирается в другом окне. Окно, которое было выбранно до вызова C-x 4 f, продолжает показывать тот же буфер, который уже показывался. Если эта команда используется, когда существует только одно окно, то это окно делится на два, одно из которых продолжает показывать то же, что и прежде, а другое показывает новый затребованный файл. Смотрите раздел Множество окон.

C-x 5 f (find-file-other-frame) аналогична этой команде, но открывает новый фрейм или делает видимым любой существующий фрейм, показывающий искомый файл. Это возможно, только если вы пользуетесь оконной системой. Смотрите раздел Фреймы и X Windows.

Если вы хотите отредактировать файл как последовательность знаков без особой перекодировки или преобразования, используйте команду M-x find-file-literally. Она обращается к файлу, как C-x C-f, но не делает преобразования формата (смотрите раздел Редактирование форматированного текста), преобразования знаковых кодов (смотрите раздел Системы кодирования) или автоматической распаковки (смотрите раздел Доступ к сжатым файлам). Если вы уже обращаетесь к этому же файлу обычным способом (не буквально), эта команда спросит вас, обратиться ли к нему в этот раз буквально.

Две переменные-ловушки позволяют расширениям изменять способ обращения к файлам. Обращение к несуществуещему файлу запускает функции в списке find-file-not-found-hooks; значение этой переменной -- это список функций, и эти функции вызываются одна за другой до тех пор, пока одна из них не вернет отличное от nil значение. Любое обращение к файлу, существующему или нет, предполагает, что find-file-hooks содержит список функций, и вызывает их все, одну за другой. В обоих случаях функции не получают аргументов. Из этих двух переменных сначала вступает в силу find-file-not-found-hooks. Эти переменные не являются обычными ловушками, и их имена оканчиваются на `-hooks', а не на `-hook', чтобы указать на это. Смотрите раздел Ловушки.

Есть несколько способов автоматически указать основной режим для редактирования файла (смотрите раздел Как выбираются основные режимы) и установить локальные переменные, определённые для этого файла (смотрите раздел Локальные переменные в файлах).

Сохранение файлов

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

C-x C-s
Сохранить текущий буфер в файле, к которому этот буфер обращается (save-buffer).
C-x s
Сохранить некоторые или все буферы в их соответствующих файлах (save-some-buffers).
M-~
Забыть, что текущий буфер был изменен (not-modified).
C-x C-w
Сохранить текущий буфер в заданный файл (write-file).
M-x set-visited-file-name
Изменить имя файла, под которым текущий буфер будет сохраняться.

Если вы хотите сохранить файл и сделать его изменения постоянными, наберите C-x C-s (save-buffer). После того, как запись закончится, C-x C-s печатает сообщение подобное этому:

Wrote /u/rms/gnu/gnu.tasks

Если же выбранный буфер не модифицирован (в нём не было сделано изменений с тех пор, как он был создан или последний раз записан), его запись не делается, так как это не имеет смысла. Вместо этого, C-x C-s печатает такое сообщение в эхо-области:

(No changes need to be saved)

Команда C-x s (save-some-buffers) предлагает записать какие-либо или все измененные буферы. Она спрашивает вас, что нужно сделать с каждым буфером. Возможные варианты ответа аналогичны вариантам для query-replace:

y
Сохранить этот буфер и спрашивать об остальных.
n
Не сохранять этот буфер, но спрашивать об остальных.
!
Сохранить этот буфер и все остальные без дальнейших вопросов.
RET
Прервать save-some-buffers и больше ничего не записывать.
.
Сохранить этот буфер и выйти из save-some-buffers, не спрашивая об остальных буферах.
C-r
Просмотреть буфер, о котором вас спросили в данный момент. Когда вы выйдите из режима View, вы снова попадаете в save-some-buffers, которая продолжает задавать вам вопросы.
C-h
Показать справочное сообщение о этих вариантах ответа.

C-x C-c, последовательность ключей для выхода из Emacs, вызывает save-some-buffers и, следовательно, задаёт эти же вопросы.

Если вы изменили буфер, но не хотите записывать изменения, вы должны предпринять некоторые действия, чтобы предотвратить это. Иначе каждый раз, когда вы используете C-x s или C-x C-c, вы можете по ошибке его записать. С одной стороны, вы можете набрать M-~ (not-modified), что сбрасывает показатель измененности буфера. Если вы сделаете так, то ни одна из команд записи не будет думать, что буфер нужно сохранять. (`~' часто используется как математический символ для обозначения отрицания, таким образом, последовательность M-~ -- это мета-отрицание). Вы могли бы также использовать set-visited-file-name (смотрите ниже), чтобы пометить буфер, как обратившийся к файлу с другим именем, который не использовался для чего-то важного. С другой стороны, вы можете отменить все изменения, сделанные с тех пор, когда к файлу обратились, или он был записан, с помощью повторного считывания текста из файла. Это называется возвращением к прежнему состоянию. Смотрите раздел Возвращение буфера. Вы могли бы также отменить все изменения, повторяя команду отмены C-x u достаточно долго; но возвращение проще.

M-x set-visited-file-name заменяет имя файла, к которому обращается текущий буфер. Она считывает новое имя файла, используя минибуфер. Затем соответственно изменяется имя буфера (если новое имя уже не используется). set-visited-file-name не записывает буфер в новый вызванный файл, она просто меняет записи внутри Emacs на случай последующего сохранения. Она так же помечает буфер как "измененный", так что C-x C-s будет его сохранять.

Если вы хотите пометить буфер как обращающийся к другому файлу и сразу его записать, используйте C-x C-w (write-file). Это совершенно точный эквивалент set-visited-file-name, за которым следует C-x C-s. Использование C-x C-s в буфере, который не обращался к файлу, имеет то же самое действие, что и C-x C-w; то есть, она считывает имя файла, метит буфер как обращающийся к этому файлу и записывает его туда. По умолчанию имя файла в буфере, который не обращался к файлу, составляется из имени буфера и каталога по умолчанию для этого буфера.

Если новое имя файла подразумевает основной режим, то C-x C-w в большинстве случаев переключает в этот режим. Команда set-visited-file-name ведет себя так же. Смотрите раздел Как выбираются основные режимы.

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

Если переменная require-final-newline не равна nil, Emacs ставит ограничитель строки в конец каждого файла, который не закончивается им, каждый раз, когда файл сохраняется или записывается. По умолчанию эта переменная равна nil.

Резервные файлы

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

Для большинства файлов решение о создании резервных копий определяется переменной make-backup-files. На большинстве операционных систем её значение по умолчанию равно t, что велит Emacs создавать резервные файлы.

Для файлов, находящихся под контролем системы управления версиями (смотрите раздел Управление версиями), это определяется переменной vc-make-backup-files. По умолчанию она равна nil, так как резервные копии излишни, раз вы записываете все предыдущие версии в системе управления версиями. Смотрите раздел Управление рабочими файлам в VC.

Существующее по умолчанию значение переменной backup-enable-predicate запрещает записывать резервные копии для файлов из каталога `/tmp'.

@hyphenation{ре-зерв-ный} По вашему выбору Emacs может сохранять либо только один резервный файл, либо несколько нумерованных резервных файлов для каждого файла, который вы редактировали.

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

Вы также можете явно запросить создание ещё одной резервной копии из буфера, даже если буфер был уже сохранён хотя бы раз. Если вы сохраните буфер с помощью C-u C-x C-s, записанная таким способом версия станет резервной, если вы сохраните буфер снова. C-u C-u C-x C-s сохраняет буфер, но сначала переносит старое содержимое файла в новый резервный файл. C-u C-u C-u C-x C-s делает и то, и другое: она создаёт резервную копию старого содержимого и готовится сделать ещё одну из вновь сохранённого содержимого, если вы сохраните буфер опять.

Одиночные или нумерованные резервные файлы

Если вы решили держать единственный резервный файл (что принимается по умолчанию), то его имя составляется путем добавления `~' к имени редактируемого файла, таким образом, резервный файл для `eval.c' назывался бы `eval.c~'.

Если вы захотите иметь серию пронумерованных резервных файлов, то их имена создаются путем добавления `.~', номера и другой `~' к исходному имени файла. Таким образом, резервные копии файла `eval.c' будут называться `eval.c.~1~', `eval.c.~2~' и так далее, проходя через такие имена, как `eval.c.~259~' и выше.

Если защита запрещает вам записывать резервные файлы под обычными именами, то они записываются как `%backup%~' в вашем начальном каталоге. Может существовать только один такой файл, поэтому доступна только резервная копия, сделанная самой последней.

Выбор единственного резервного файла или нескольких управляется переменной version-control. Её возможные значения:

t
Создавать нумерованные резервные файлы.
nil
Создавать нумерованные резервные файлы для файлов, которые уже имеют нумерованные файлы. Иначе создавать один резервный файл.
never
Никогда не создавать нумерованные файлы, всегда делать одиночный резервный файл.

Вы можете установить version-control локально в отдельном буфере, для управления созданием резервных копий файла этого буфера. Например, режим Rmail локально устанавливает version-control на never, чтобы быть уверенным, что для Rmail-файла существует только один резервный файл. Смотрите раздел Локальные переменные.

Если вы установите переменную среды `VERSION_CONTROL', чтобы указать различным утилитам GNU, что делать с резервными файлами, Emacs также подчиняется ей, устанавливая соответственно во время запуска переменную Лиспа version-control. Если значение этой переменной среды равно `t' или `numbered', то version-control становится равной t; если это значение равно `nil' или `existing', то version-control становится nil; если это `never' или `simple', то version-control устанавливается в значение never.

Автоматическое удаление резервных файлов

Чтобы предотвратить неограниченное потребление пространства на диске, Emacs может удалять пронумерованные резервные версии файлов автоматически. Обычно Emacs хранит только несколько первых и несколько последних резервных файлов, уничтожая все находящиеся между ними. Это происходит каждый раз, когда создаётся новый резервный файл.

Двумя переменными, контролирующими удаление, являются kept-old-versions и kept-new-versions. Их значения --- это, соответственно, номер самой старой резервной копии файла (наименьший номер), которая должна быть сохранена, и номер самой последней копии (наибольший номер), которая должна сохраняться каждый раз, когда создаётся новая копия. Помните, что эти значения используются сразу после того, как создастся новая резервная копия; вновь созданная копия включается в счетчик kept-new-version. По умолчанию обе переменные равны 2.

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

Команда Dired . (точка) также может быть использована для удаления старых версий. Смотрите раздел Удаление файлов с помощью Dired.

Копирование vs. переименование

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

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

Изменение владельца обычно является хорошей идеей, поскольку тогда всегда видно, кто последним редактировал файл. Кроме того, владельцы резервных копий показывают, кто сделал эти версии. Иногда существует файл, чей владелец не должен изменяться; хорошая идея для таких файлов --- включить локальные списки переменных для установки backup-by-copying-when-mismatch (смотрите раздел Локальные переменные в файлах).

Выбор переименования или копирования управляется тремя переменными. По умолчанию делается переименование. Если переменная backup-by-coping -- не nil, то используется копирование. В противном случае, если переменная backup-by-copying-when-linked не равна nil, то делается копирование для файлов, которые имеют несколько имён, но может всё же делаться переименование, когда редактируемый файл имеет только одно имя. Если переменная backup-by-copying-when-mismatch -- не nil, тогда, если переименование привело бы к изменению владельца файла или группы, то делается копирование. backup-by-copying-when-mismatch по умолчанию равна t, если вы запустили Emacs как привилегированный пользователь.

@hyphenation{соз-да-ет} Когда файл находится под управлением системы контроля версий (смотрите раздел Управление версиями), Emacs обычно не создаёт резервных копий как обычно. Но извлечение и фиксирование отчасти подобны созданию резервных копий. Они похожи, к сожалению, и тем, что как правило разрушают жесткие ссылки, разъединяя имя файла, к которому вы обратились, и все другие имена этого же файла. Это не вина Emacs --- это делает система управления версиями.

Защита от одновременного редактирования

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

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

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

Если вы начнете изменять буфер, когда файл, к которому он обращается, захвачен кем-то еще, это приведет к столкновению, и Emacs спросит вас, что делать, вызвав лисповскую функцию ask-user-about-lock. Вы можете переопределить эту функцию для своих нужд. Стандартное определение этой функции задаёт вам вопрос и принимает три возможных ответа:

s
Перехватить захват. Тот пользователь, кто уже редактировал файл, теряет захват, а вы его приобретаете.
p
Продолжать. Идти дальше и редактировать файл, несмотря на то, что он кем-то захвачен.
q
Выйти. Это приводит к ошибке (file-locked), а изменения, которые вы пытались сделать в буфере, в действительности не будут иметь места.

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

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

Если в Emacs или в операционной системе случается фатальный сбой, это может оставить файлы захвата, которые уже потеряли актуальность. Поэтому вы можете иногда получить предупреждение о мнимых столкновениях. Когда вы обнаружите, что столконение ложно, просто используйте p, чтобы велеть Emacs продолжать.

Каждый раз, когда Emacs записывает буфер, он сначала сверяет дату последней модификации файла, существующего на диске, чтобы увидеть, что она не изменялась с тех самых пор, как к файлу обращались или его записывали последний раз. Если дата не совпадает, то это означает, что изменения были произведены в файле каким-то другим способом, и что эти изменения могут быть потеряны, если Emacs сохранит буфер на самом деле. Чтобы предотвратить это, Emacs печатает предостерегающее сообщение и запрашивает перед записью подтверждение. Иногда вы знаете, почему файл был изменен, и знаете, что это не имеет значения; в этом случае вы можете ответить yes и продолжить редактирование. В противном случае, вы должны отменить запись с помощью C-g и исследовать ситуацию.

Первое, что вы должны сделать, когда пришло извещение об одновременном редактировании, -- распечатать каталог с помощью C-u C-x C-d (смотрите раздел Каталоги файлов). Это покажет вам текущего автора. Вы должны будете попытаться связаться и предупредить его, чтобы он не продолжал редактирование. Чаще всего, следующий шаг -- записать содержимое вашего буфера Emacs под другим именем и использовать diff, чтобы сравнить два файла.

Возвращение буфера

Если вы сделали обширные изменения в файле, а затем изменили ваше мнение о них, то вы можете от них избавиться, считав предыдущую версию этого файла. Чтобы сделать это, используйте M-x revert-buffer, она действует в текущем буфере. Так как от безусловного возврата буфера может пропасть много работы, вы должны подтвердить эту команду вводом yes.

revert-buffer сохраняет точку на том же самом расстоянии (измеренном в знаках) от начала файла. Если файл был отредактирован только слегка, то после возвращения вы очутитесь примерно в той же части текста, в которой и были. Если вы сделали кардинальные изменения, то то же самое значение точки в старом файле может ссылаться на совершенно другой кусок текста.

Возвращение помечает буфер как "неизмененный" до тех пор, пока не будут сделаны другие изменения.

Некоторые виды буферов, чье содержимое отражает отличные от файлов данные, такие как буферы Dired, также могут быть возвращены. Для них возвращение означает повторное считываение их содержимого из соответствующей базы данных. Буферы, созданные явно с помощью C-x b, не могут быть возвращены; revert-buffer сообщает об ошибке, когда её просят сделать это.

Когда вы редактируете файл, который изменяется часто и автоматически --- например, протокол вывода от ещё работающего процесса -- может оказаться удобным, если бы Emacs возвращал файл без подтверждения всякий раз, когда вы снова обращаетесь к этому файлу с помощью C-x C-f.

Чтобы запросить такое поведение, установите переменную revert-without-query равной списку регулярных выражений. Когда имя файла соответствует одному из этих регулярных выражений, find-file и revert-buffer будут возвращать его автоматически, если он изменился -- при условии, что сам буфер не был модифицирован. (Если вы редактировали текст, сбрасывать ваши изменения будет нехорошо.)

Самосохранение: защита от гибели

Emacs время от времени (основываясь на подсчете нажатых вами клавиш) записывает все посещенные файлы без запроса. Это называется самосохранением. Оно убережет вас от потери большого количества работы, если система рухнет.

Когда Emacs определяет, что пришло время для самосохранения, то каждый буфер рассматривается и записывается, если для него включено самосохранение, и он изменялся с тех пор, как последний раз был самосохранён. Во время самосохранения в эхо-области отображается сообщение `Auto-saving...', если какой-либо файл действительно сохраняется. Ошибки, появляющиеся во время самосохранения, отлавливаются так, что они не мешают выполнению набранных вами команд.

Файлы для самосохранения

Самосохранение обычно не записывает в файлы, к которым вы обратились, так как может быть очень нежелательно записывать программу, которая находится в несогласованном состоянии, когда вы сделали половину планируемых изменений. Вместо этого самосохранение делается в другой файл, который называется файлом для самосохранения, а посещенный файл изменяется только тогда, когда вы явно потребуете записать его (например, с помощью C-x C-s).

Обычно имя файла для самосохранения создаётся добавлением знака `#' перед и после имени файла, к которому вы обратились. Таким образом, буфер, обращающийся к файлу `foo.c', будет самосохранен в файл `#foo.c#'. Большинство буферов, которые не обращались к файлам, самосохраняются, только если вы явно потребуете этого; когда они автоматически записываются, имя файла для самосохранения создаётся добавлением к имени буфера знаков `#%' в начале и `#' в конце. Например, буфер `*mail*' , в котором вы составляете отправляемые сообщения, самосохраняется в файл с именем `#%*mail*#'. Имена файлов для самосохранения конструируются таким образом, если вы не перепрограммируете часть Emacs, чтобы делалось что-то иное (функции make-auto-save-file-name и auto-save-file-name-p). Имя файла, которое будет использоваться для самосохранения в буфере, составляется, когда в этом буфере включается самосохранение.

Когда вы удаляете значительную часть текста большого буфера, самосохранение в нём временно выключается. Это делается по той причине, что если вы удалили текст неумышленно, самосохранённый файл может оказаться для вас полезнее, если удалённый текст всё ещё остается в нём. Чтобы после этого снова разрешить самосохранение, запишите буфер командой C-x C-s или используйте C-u 1 M-x auto-save.

Если вы хотите, чтобы в файле, к которому вы обратились, выполнялось самосохранение, установите переменную auto-save-visited-file-name в отличное от nil значение. В этом режиме в действительности нет различий между самосохранением и явным сохранением.

Файл самосохранений удаляется, когда вы записываете содержимое буфера в файл, к которому он обращался. Чтобы воспрепятствовать этому, установите переменную delete-auto-save-files равной nil. Изменение имени посещенного файла с помощью C-x C-w или set-visited-file-name переименовывает файл для самосохранения, чтобы он соответствовал имени нового посещенного файла.

Управление самосохранением

Каждый раз, когда вы обращаетесь к файлу, для буфера этого файла включается самосохранение, если переменная auto-save-default не равна nil (но не в пакетном режиме; смотрите раздел Вход и выход из Emacs). По умолчанию эта переменная равна t, поэтому включённое самосохранение -- это обычное состояние буферов, работающих с файлами. Самосохранение может включаться или выключаться для любого существующего буфера с помощью команды M-x auto-save-mode. Подобно другим командам второстепенных режимов, M-x auto-save-mode включает самосохранение при положительном аргументе и выключает, когда аргумент равен нулю или отрицателен; без аргумента она переключает режим.

Emacs производит самосохранение периодически, основываясь на подсчете числа знаков, набранных вами с того момента, как самосохранение было сделано в последний раз. Переменная auto-save-interval определяет, сколько знаков приходится между двумя самосохранениями. По умолчанию она равна 300.

Самосохранение также производится, когда вы перестаете печатать на некоторое время. Переменная auto-save-timeout говорит, сколько секунд должен ждать Emacs то того, как сделать самосохранение (а также, возможно, и сборку мусора). (Действительный период времени больше, если теущий буфер велик; это эвристика, цель которой -- не мешать вам, когда вы редактируете длинные буферы, самосохранение в которых занимает заметное время.) Самосохранение во время периодов бездействия выполняет две задачи: во-первых, оно гарантирует, что ваша работа сохраняется, если вы отошли на некоторое время от терминала; во-вторых, оно может позволить избежать самосохранения в то время, когда вы на самом деле печатаете.

Emacs также выполняет самосохранение, когда получает фатальную ошибку. Это включает уничтожение задания Emacs с помощью команды оболочки, как `kill %emacs', или в результате разъединения телефонной линии или связи по сети.

Вы можете явно запросить самосохранение с помощью команды M-x do-auto-save.

Восстановление данных из самосохранения

Вы можете использовать содержимое файла самосохранения для восстановления потерянных данных, запустив команду M-x recover-file RET файл RET. Эта команда обращается к файлу и затем (после вашего подтверждения) переписывает содержание из его самосохранённого файла `#файл#'. Вы можете потом сохранить этот буфер при помощи C-x C-s, чтобы поместить восстановленный текст в сам файл. Например, чтобы восстановить файл `foo.c' из его файла для самосохранения `#foo.c#', сделайте следующее:

M-x recover-file RET foo.c RET
yes RET
C-x C-s

Перед тем как запросить у вас подтверждение, M-x recover-file показывает распечатку каталога, описывающую заданный файл и файл самосохранения, так что вы можете сравнить их размеры и даты. Если файл для самосохранения старше, то M-x recover-file не предлагает его считывать.

Если Emacs или комьютер потерпели крах, вы можете восстановить все файлы, которые вы редактировали, из их самосохранённых файлов при помощи команды M-x recover-session. Она сначала показывает перечень записанных прерванных сеансов. Переместите точку к нужной вам и наберите C-c C-c.

Затем recover-session спрашивает о каждом файле, который редактировался во время этого сеанса, нужно ли его восстанавливать. Если вы отвечаете y, она вызывает recover-file. Эта команда работает обычным способом: показывает даты оригинального файла и его самосохранённой версии и спрашивает ещё раз, нужно ли его восстанавливать.

Когда recover-session завершается, все файлы, которые вы решили восстановить, присутствуют в буферах Emacs. Теперь вам нужно их сохранить. Только это -- их сохранение -- обновляет сами файлы.

Прерванные сеансы записываются для последующего восстановления в файлах с именами `~/.saves-pid-машина'. Часть `~/.saves' этих имён получается из значения auto-save-list-file-prefix. Вы можете сделать так, чтобы записи о сеансах держались в другом месте, устанавливая эту переменную в вашем файле `.emacs', но вам также придется переопределить recover-session, чтобы она искала в новом месте. Если в файле `.emacs' вы установите auto-save-list-file-prefix равной nil, сеансы не будут записываться для восстановления.

Псевдонимы файлов

Символьные ссылки и жесткие ссылки позволяют одному и тому же файлу иметь несколько имён. Жёсткие ссылки -- это альтернативные имена, ссылающиеся непосредственно на файл; все имена одинаково правильны, и ни одно из них не является предпочтительным. Напротив, символьные ссылки --- это вид определённых псевдонимов: когда файл `foo' является символьной ссылкой на `bar', вы можете использовать оба имени, но действительным именем будет `bar', тогда как `foo' -- это просто псевдоним. Более сложные ситуации возникают, когда символьные ссылки указывают на каталоги.

Если вы обращаетесь к одному и тому же файлу по двум именам, Emacs обычно создает два разных буфера, но предупреждает вас об этой ситуации.

Если вы хотите избежать обращения к одному и тому же файлу в двух буферах под разными именами, установите переменную find-file-existing-other-name в отличное от nil значение. Тогда find-file использует существующий буфер, обращающийся к этому файлу, независимо от того, какое имя вы зададите.

Если переменная find-file-visit-truename не равна nil, то для буферов записывается истинные имена файлов (получаемые заменой всех символьных ссылок на их целевые имена), а не имена, заданные вами. Установка find-file-visit-truename также подразумевает действие find-file-existing-other-name.

Управление версиями

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

Интерфейс Emacs для управления версиями называется VC. Его команды работают с тремя системами управления версиями -- RCS, CVS и SCCS. Проект GNU рекомендует RCS и CVS, которые являются свободными программами, и их можно получить от Фонда Свободного Программного Обеспечения.

Введение в управление версиями

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

Этот раздел предоставляет общий обзор управления версиями и описывает системы управления версиями, которые поддерживает VC. Вы можете пропустить этот раздел, если знакомы с системой управления версиями, которую хотите использовать.

Поддерживаемые системы управления версиями

На данный момент VC работает с тремя разными системами управления версиями или "постпроцессорами": RCS, CVS и SCCS.

RCS -- это свободная система управления версиями, её можно получить от Фонда Свободного Программного Обеспечения. Вероятно, это наиболее развитый из поддерживаемых постпроцессоров, и команды VC концептуально ближе всего к RCS. Почти все, что вы можете делать с RCS, можно сделать через VC.

CVS построена поверх RCS и расширяет возможности RCS, позволяя более сложное управление выпусками и разработку многими пользователями. VC поддерживает основные операции редактирования под CVS, но для некоторых менее частых задач вам все же понадобится вызывать CVS из командной строки. Заметьте, что до использования CVS вы должны настроить репозиторий, но это слишком сложная тема, чтобы её здесь рассматривать.

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

Концепции управления версиями

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

Файл, сопровождаемый управлением версий, иногда называется рабочим файлом, соответствующим его мастер-файлу. Вы редактируете рабочий файл и делаете в нём изменения, как вы делали бы йдля обычного файла. (В SCCS и RCS вы должны блокировать файл перед тем, как начать его редактировать.) После того, как вы сделали некоторые изменения, вы фиксируете этот файл, что записывает эти изменения в мастер-файле вместе с журнальной записью для них.

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

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

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

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

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

Управление версиями и строка режима

Когда вы обращаетесь к файлу, который находится под контролем системы управления версиями, Emacs показывает это в строке режима. Например, `RCS-1.3' говорит, что для этого файла используется RCS, а текущая версия -- 1.3.

Знак между именем постпроцессора и номером версии показывает статус этого файла в системе управления версиями. Дефис `-' говорит, что рабочий файл не заблокирован (если блокирование используется) или не изменен (если блокирование не используется). Знак `:' показывает, что файл блокирован или изменен. Если файл блокировал какой-то другой пользователь (скажем, `jim'), это отображается как `RCS:jim:1.3'.

Основы редактирования с управлением версиями

Основная команда VC -- это команда общего назначения, которая либо блокирует, либо фиксирует файл в зависимости от ситуации.

C-x C-q
C-x v v
Делает следующую логическую операцию управления версиями для этого файла.

Строго говоря, команда для этого называется vc-next-action, она привязана к C-x v v. Однако, обычное значение C-x C-q --- делать буферы, предназначенные только для чтения, доступными для записи или наоборот; мы расширили её так, чтобы она правильно делала это же для файлов, находящихся под контролем системы управления версиями, производя подходящие операции. Когда вы набираете C-x C-q в зарегистрированнм файле, она ведет себя, как C-x v v.

Точное действие этой команды зависит от состояния файла и от того, использует ли система управления версиями блокирование или нет. SCCS и RCS обычно используют блокирование; CVS обычно не использует.

Основы управления версиями с блокированием

Если для файла применяется блокирование (как в в случае с SCCS и RCS в режиме по умолчанию), C-x C-q может либо блокировать файл, либо зафиксировать его:

  • Если файл не заблокирован, C-x C-q блокирует его и делает доступным для записи, чтобы вы могли его изменять.
  • Если файл заблокирован вами и содержит изменения, C-x C-q фиксирует эти изменения. Для этого она сначала считывает журнальную запись новой версии. Смотрите раздел Буфер журнальной записи.
  • Если файл заблокирован вами, но не содержит изменений с тех пор, как вы его блокировали, C-x C-q снимает блокировку и делает файл опять доступным только для чтения.
  • Если файл заблокирован кем-то еще, C-x C-q спрашивает вас, хотите ли вы "украсть блокировку" у этого пользователя. Если вы ответите да, то файл становится блокированным вами, но человеку, который раньше заблокировал его, посылается сообщение, чтобы проинформировать о случившемся.

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

Основы управления версиями без блокирования

Когда блокирования нет -- по умолчанию в CVS -- рабочие файлы всегда доступны для записи; вам не нужно ничего делать перед тем, как начать редактирование. Индикатором статуса в строке режима служит `-', если файл не изменен; он заметяется на `:', как только вы сохраняете любые изменения в рабочем файле.

Вот что делает C-x C-q при использовании CVS:

  • Если какой-то другой пользователь зафиксировал свои изменения в мастер-файле, Emacs спрашивает вас, хотите ли вы влить эти изменения в ваш рабочий файл (смотрите раздел Объединение ветвей). Вы обязаны сделать это до того, как сможете зафиксировать свои собственные изменения.
  • Если в мастер-файле нет изменений, но вы модификацировали ваш рабочий файл, C-x C-q фиксирует ваши изменения. Для этого она сначала считывает журнальную запись для новой версии. Смотрите раздел Буфер журнальной записи.
  • Если файл не изменен, C-x C-q ничего не делает.

Эти правила применимы также и в том случае, если вы используете RCS в режиме, когда она не требует блокирования, за исключением того, что автоматическое объединение с мастер-файлом не реализовано. К сожалению, это означает, что вас не информируют, если ещё один пользователь зафиксировал изменения в том же файле после того, как вы начали редактирование, и когда это происходит, его изменения в результате исчезнут в вашей зафиксированной версии (хотя они останутся в мастер-файле, так что не окажутся полностью потерянными). Поэтому вы должны убедиться, что текущая версия осталась неизмененной перед тем как фиксировать свои изменения. Мы надеемся устранить этот риск и предоставить автоматическое объединение для RCS в будущей версии Emacs.

Кроме того, даже в этом режиме RCS блокирование возможно, хоть и необязательно; C-x C-q в неизмененном файле блокирует этот файл, так же, как с RCS в обычном (блокирующем) режиме.

Буфер журнальной записи

Когда вы фиксируете изменения, C-x C-q сначала считывает журнальную запись. Она поднимает буфер с именем `*VC-Log*', в котором вы вводите журнальную запись. Когда вы завершили, нажмите C-c C-c в буфере `*VC-Log*'. Только тогда происходит действительное фиксирование.

Чтобы прервать фиксирование, просто не набирайте C-c C-c в этом буфере. Вы можете переключать буферы и делать другое редактирование. Пока вы не пытаетесь зафиксировать другой файл, запись, которую вы редактировали, остается в буфере `*VC-Log*', и вы можете в любое время вернуться в этот буфер и завершить фиксирование.

Если вы модифицируете несколько исходных файлов с одной целью, часто бывает удобно указать одинаковую журнальную запись для многих файлов. Чтобы сделать так, используйте историю предыдущих журнальных записей. Предназначенные для этого команды M-n, M-p, M-s и M-r работают так же, как команды истории минибуфера (за исключением того, что они применяются вне минибуфера).

Каждый раз, когда вы фиксируете файл, буфер журнальной записи помещается в режим VC Log, что влечет запуск двух ловушек: text-mode-hook и vc-log-mode-hook. Смотрите раздел Ловушки.

Просмотр и сравнение старых версий

Одна из удобных возможностей систем управления версиями --- возможность просмотра любой версии файла или сравнения двух версий.

C-x v ~ версия RET
Показывает заданную версию файла, к которому вы обратились, в отдельном буфере.
C-x v =
Сравнивает текущее содержимое буфера с последней зафиксированной версией этого файла.
C-u C-x v = файл RET старая-вер RET новая-вер RET
Сравнивает две заданные версии файла.
C-x v g
Выводит результат команды CVS annotate с использованием разных цветов.

Чтобы просмотреть старую версию in toto, обратитесь к файлу и наберите C-x v ~ версия RET (vc-version-other-window). Это поместит текст указанной версии в файл с именем `имя-файла.~версия~' и обратится к нему в новом буфере в отдельном окне. (В RCS, вы также можете выбрать старый буфер и создать из него новую ветвь. Смотрите раздел Множество ветвей файла.)

Но обычно более удобно сравнивать две версии файла с помощью команды C-x v = (vc-diff). Просто C-x v = сравнивает текущее содержимое буфера (сохраняя его в файл, если требуется) с последней зафиксированной версией этого файла. C-u C-x v = с числовым аргументом считывает имя файла и номера двух версий, а затем сравнивает эти версии указанного файла.

Если вы зададите вместо зарегистрированного файла имя каталога, эта команда сравнивает заданные версии всех зарегистрированных файлов в этом каталоге и его подкаталогах.

Вы можете задать зафиксированную версию числом; пустой ввод обозначает текущее содержимое рабочего файла (оно может отличаться от всех зафиксированных версий). Вы также можете задать вместо одного или обоих номеров версий имя снимка (смотрите раздел Снимки).

Эта команда работает путем запуска утилиты diff, передавая ей аргументы из переменной diff-switches. Она показывает вывод в особом буфере в другом окне. В отличие от команды M-x diff, C-x v = не пытается определить позиции различий в старой и новой версиях. Так делается, потому что как правило одна или обе версии не существуют в момент сравнения в виде файлов; они существуют только в записях в мастер-файле. Смотрите раздел Сравнение файлов, для получения большей информации о M-x diff.

Для файлов, управляемых CVS, вы можете посмотреть результат команды CVS annotate с использованием разных цветов для улучшения внешнего вида. Используйте для этого команду M-x vc-annotate. Красным обозначается новое, синим -- старое, а промежуточные цвета обозначают промежуточные версии. Префиксный аргумент n задаёт коэффициент растяжения по временной шкале; он говорит, что каждый цвет покрывает в n раз больший период времени.

Второстепенные команды VC

Этот раздел объясняет второстепенные команды VC; те, что вы могли бы использовать раз в день.

Регистрирование файла для управления версиями

Вы можете поместить любой файл под контроль системы управления версиями, просто обратясь к нему и набрав затем C-x v i (vc-register).

C-x v i
Регистрирует файл в системе управления версиями.

Чтобы зарегистрировать файл, Emacs должен выбрать, какую систему управления версиями для него использовать. Вы можете указать свой выбор явно, устанавливая vc-default-back-end в значения RCS, CVS или SCCS. Иначе, если есть подкаталог с именем `RCS', `SCCS' или `CVS', Emacs использует соответствующую систему управления версиями. В отсутствие каких-либо указаний, по умолчанию выбирается RCS, если в системе установлена RCS, иначе SCCS.

Если применяется блокирование, C-x v i оставляет файл неблокированным и запрещает в запись. Наберите C-x C-q, если вы хотите начать в нём редактирование. После регистрирования с использованием CVS вы должны зафиксировать изменения, набрав C-x C-q.

Первоначальной версии вновь зарегистрированного файла присваивается номер 1.1, по умолчанию. Вы можете задать другое значение по умолчанию, устанавливая переменную vc-default-init-version, или вы можете дать C-x v i числовой аргумент; тогда она считывает номер версии для этого конкретного файла в минибуфере.

Если vc-initial-comment отлична от nil, C-x v i считывает начальный комментарий, описывающий предназначение данного исходного файла. Начальный комментарий считывается так же, как журнальные записи (смотрите раздел Буфер журнальной записи).

Команды VC для выяснения статуса файла

C-x v l
Показывает состояние файла в системе управления версиями и историю изменений.

Чтобы просмотреть подробную информацию о статусе версии и историю файла, наберите C-x v l (vc-print-log). Это покажет историю изменений текущего файла, в том числе текст журнальных записей. Вывод появляется в другом окне.

Отмена действий над версиями

C-x v u
Возвращает буфер и его файл к последней зафиксированной версии.
C-x v c
Удаляет последнее внесенное изменение из мастер-файла для файла, к которому вы обратились. Это отменяет ваше последнее фиксирование.

Если вы хотите сбросить ваши текущие изменения и вернуть файл к его последней версии, используйте C-x v u (vc-revert-buffer). Файл остается неблокированным; если используется блокирование, до того, как сможете изменять этот файл, вы должны сначала снова его заблокировать. C-x v u требует подтверждения, если только она не видит, что вы не вносили изменения со времени последего фиксирования.

C-x v u также нужна для разблокирования файла, когда вы блокировали его, а потом решили не изменять.

Чтобы отменить уже зафиксированное изменение, используйте C-x v c (vc-cancel-version). Эта команда сбрасывает все записи о последней фиксированной версии. C-x v c также предлагает вернуть ваш рабочий файл и буфер к предыдущей версии (к той, что предшествовала удаляемой).

Если вы отвечаете no, VC сохраняет ваши изменения в буфере и блокирует файл. Такая возможность полезна, когда вы зафиксировали изменение, а затем обнаружили в нём тривиальную ошибку; вы можете отменить фиксирование, исправить ошибку и снова зафиксировать файл.

Когда C-x v c не возвращает буфер, она вместо этого сворачивает все заголовки версий (смотрите раздел Вставка заголовков версий). Это делается по той причине, что буфер больше не соответствует никакой существующей версии. Если вы снова зафиксируете его, заголовки будут раскрыты правильно относительно нового номера версии.

Однако, автоматически свернуть заголовок RCS `$Log$' невозможно. Если вы пишете этот заголовок, вы должны свернуть его вручную -- удалив вхождение для версии, которую вы отменили.

Будьте осторожны при вызове C-x v c, так как при этом легко потерять много работы. Чтобы помочь вам не допустить ошибки, эта команда всегда требует подтверждения с yes. Обратите внимание также на то, что эта команда выключена под CVS, поскольку там отмена версий очень опасна и не рекомендуется.

Dired под VC

Когда вы работаете над большой программой, часто бывает полезно узнать, какие файлы были изменены в пределах целого дерева каталогов, или просмотреть статус всех файлов с управлением версиями одновременно и произвести какие-то операции над версиями для набора файлов. Вы можете использовать команду C-x v d (vc-directory), чтобы создать распечатку каталога, который включает только файлы, имеющие отношение к системе управления версиями.

C-x v d создаёт буфер, использующий режим VC Dired. Он выглядит как обычный буфер Dired (смотрите раздел Dired, редактор каталогов); однако, как правило в нём показаны только стоящие упоминания файлы (блокированные или необновленные). Это называется сжатым показом. Если вы установите переменную vc-dired-terse-display равной nil, то VC Dired показывает все относящиеся к делу файлы -- те, что находятся под контролем системы управления версиями, плюс все подкаталоги (полный показ). Команда v t в буфере VC Dired переключает между сжатым и полным показом (смотрите раздел Команды VC Dired).

По умолчанию VC Dired производит рекурсивую распечатку заслуживающих упоминания или релевантных файлов в заданном каталоге и ниже. Вы можете изменить это, устанавливая переменную vc-dired-recurse равной nil; тогда VC Dired показывает только файлы текущего каталога.

Строка для отдельного файла показывает состояние версии на месте числа жестких ссылок, владельца, группу и размер файла. Если файл не изменен, синхронизирован с мастер-файлом, статус версии пуст. Иначе он состоит из текста в круглых скобках. Под RCS и SCCS показывается имя пользователя, блокировавшего этот файл; под CVS используется сокращенная версия вывода `cvs status'. Вот пример с использованием RCS:

 /home/jim/project:
 -rw-r--r-- (jim) Apr 2 23:39 file1
 -r--r--r-- Apr 5 20:21 file2

Файлы `file1' и `file2' находятся под управлеием RCS, `file1' блокировал пользователь jim, а `file2' неблокирован.

Вот пример с использованием CVS:

 /home/joe/develop:
 -rw-r--r-- (modified) Aug 2 1997 file1.c
 -rw-r--r-- Apr 4 20:09 file2.c
 -rw-r--r-- (merge) Sep 13 1996 file3.c

Здесь `file1.c' изменен по отношению к репозиторию, а `file2.c' не изменен. `file3.c' изменен, но в репозитории были также зафиксированы другие изменения -- вам нужно объединить их в рабочем файле перед фиксированием.

Когда VC Dired показывает подкаталоги (в режиме "полного" показа), он опускает некоторые из них, которые никогда не могут содержать файлов под контролем системы управления версиями. По умолчанию это включает каталоги, создаваемые этими системами, такие как `RCS' и `CVS'; вы можете настраивать это, устанавливая переменную vc-directory-exclusion-list.

Вы можете подобрать подходящий формат VC Dired, набрав C-u C-x v d -- как в обычном Dired, что позволяет вам указывать дополнительные ключи для команды ls.

Команды VC Dired

Все обычные команды Dired работают как всегда и в режиме VC Dired, за исключением v, которая переопределена как префикс управления версиями. Вы можете вызывать команды VC, такие как vc-diff и vc-print-log, набирая v = или v l и так далее. Большинство этих команд применяются к имени файла на текущей строке.

Команда v v (vc-next-action) обрабатывает все помеченные файлы, так что вы можете заблокировать или зафиксировать несколько файлов одновременно. Если она работает более чем с одним файлом, то обрабатывает каждый файл в соответствии с его статусом; таким образом, она может блокировать один файл, но зафиксировать другой. Возможно, это смутит вас; но вы вольны избежать путаницы, помечая набор файлов с одним и тем же статусом.

Если какой-либо файл требует фиксирования, v v считывает единственную журнальную запись и использует её для всех фиксируемых файлов. Это удобно для одновременного регистрирования или фиксирования нескольких файлов как частей одного изменения.

Вы можете в любое время переключаться между сжатым показом (только блокированные или необновленные файлы) и полным показом, набирая v t vc-dired-toggle-terse-mode. Есть также особая команда * l (vc-dired-mark-locked), которая помечает все заблокированные в данный момент файлы (или, для CVS, все необновленные). Таким образом, набор * l t k -- это другой способ удалить из буфера все файлы, кроме тех, что сейчас заблокированы.

Множество ветвей файла

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

Главная линия развития файла обычно называется стволом. Версии ствола обычно нумеруются как 1.1, 1.2, 1.3, etc. На любой из этих версий вы можете начать независимую ветвь. Ветвь, начинающаяся на версии 1.2 имела бы номер 1.2.1.1, а последующие версии этой ветви имели бы номера 1.2.1.2, 1.2.1.3, 1.2.1.4 и так далее. Если есть вторая ветвь, также начинающаяся на версии 1.2, она состояла бы из версий 1.2.2.1, 1.2.2.2, 1.2.2.3, etc.

Если вы опускаете последний компонент в номере версии, это называется номером ветви. Он ссылается на самую верхнюю существующую версию этой ветви -- её головную версию. Ветви в примере выше имеют номера 1.2.1 и 1.2.2.

Переключение между ветвями

Чтобы переключиться между ветвями, введите C-u C-x C-q и укажите номер версии, который вы хотите выбрать. Тогда к этой версии делается обращение в неблокированном (защищенном от записи) режиме, так что вы можете просмотреть её перед блокированием. Переключение ветвей таким способом допускается только тогда, когда файл блокирован.

Вы можете опустить номер второстепенной версии, задавая таким образом только номер ветви; это переносит вас к головной версии выбранной ветви. Если вы наберете просто RET, Emacs переходит к самой верхней версии ствола.

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

Создание новых ветвей

Чтобы создать новую ветвь из головной версии (последней в своей ветви), сначала выберите эту версию, если необходимо, заблокируйте её командой C-x C-q и делайте нужные вам изменения. Затем, когда вы фиксируете изменения, используйте C-u C-x C-q. Это позволит вам задать номер для новой версии. Вы должны задать подходящий номер для ветви, отходящей от текущей версии. Например, если текущая версия --- 2.5, то номер ветви должен быть 2.5.1, 2.5.2 и так далее в зависимости от номеров существующих ветвей в этой точке.

Чтобы создать новую ветвь от более старой версии (той, что уже не является головной в ветви), сначала выберите эту версию (смотрите раздел Переключение между ветвями), затем заблокируйте её с помощью C-x C-q. Когда вы блокируете старую версию, вас попросят подтвердить, что вы действительно имели в виду создание новой ветви, -- если вы ответите нет, вам предоставят возможность блокировать вместо этого последнюю версию.

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

После того как ветвь создана, вы "остаетесь" в ней. Это означает, что последующие фиксирования создают новые версии в этой ветви. Чтобы покинуть ветвь, вы должны явно выбрать другую версию с помощью C-u C-x C-q. Чтобы перенести изменения из одной ветви в другую, используйте команду объединения, описанную в следующем разделе.

Объединение ветвей

Когда вы закончили изменения в конкретной ветви, вам часто будет нужно внести их в главную линию разработки файла (ствол). Это нетривиальная процедура, потому что в стволе тоже могло идти развитие, поэтому вы должны объединить изменения с файлом, который уже был изменен иначе. VC позволяет вам сделать это (и другие вещи) при помощи команды vc-merge.

C-x v m (vc-merge)
Вливает изменения в рабочий файл.

C-x v m (vc-merge) берёт набор изменений и вливает их в текущую версию рабочего файла. Сначала она спрашивает у вас номер ветви или пару номеров версий в минибуфере. Затем она находит отличия от этой ветви или между двумя заданными версиями и объединяет их в текущей версии текущего файла.

В качестве примера предположим, что вы завершили некоторое добавление в ветви 1.3.1. Тем временем разработка ствола продвинулась до версии 1.5. Чтобы влить изменения в ствол, сначала перейдите в головную версию ствола, набрав C-u C-x C-q RET. Версия 1.5 теперь стала текущей. Если для этого файла используется блокирование, наберите C-x C-q для блокирования версии 1.5, чтобы вы могли её изменять. Затем наберите C-x v m 1.3.1 RET. Это возьмет весь набор изменений в ветви 1.3.1 (относительно версии 1.3, где ветвь была начата, и до самой последней версии этой ветви) и вливает их в текущую версию рабочего файла. Теперь вы можете зафиксировать измененный файл, созадвая таким образом версию 1.6, содержащую изменения из ветви.

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

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

Когда во время объединения возникают конфликты, VC замечает их, говорит вам о них в эхо-области и спрашивает, хотите ли вы помочь в объединении. Если вы отвечаете да, VC запускает сеанс Ediff (смотрите раздел `Ediff' в The Ediff Manual).

Если вы говорите нет, в файл вставляются оба конфликтующих изменения, окруженные маркерами конфликта. Пример ниже показывает, как выглядят конфликтующие области; файл называется `имя-файла', а номер текущей версии в мастер-файле, где находятся с изменения пользователя Б -- 1.11.

<<<<<<< имя-файла
 Версия пользователя А
=======
 Версия пользователя Б
>>>>>>> 1.11

Теперь вы можете разрешить конфликт, редактируя файл вручную. Или вы можете напечатать M-x vc-resolve-conflicts после обращения к файлу. Это запускает сеанс Ediff, как описано выше.

Многопользовательские разветвления

Часто нескольким разработчикам бывает полезно работать одновременно над различными ветвями файла. CVS позволяет это по умолчанию; в RCS это возможно, если вы создадите несколько исходных каталогов. Каждый исходный каталог должен иметь ссылку с именем `RCS', которая указывает на общий каталог с мастер-файлами RCS. Тогда каждый исходный каталог может хранить собственный набор выбранных версий, но все они разделяют одни общие записи RCS.

Этот метод работает надежно и автоматически, при условии, что исходные файлы содержат заголовки RCS о версии (смотрите раздел Вставка заголовков версий). Эти заголовки позволяют Emacs всегда точно знать номер версии, присутсвующей в рабочем файле.

Если в файлах нет заголовков версии, вы должны в каждом сеансе явно говорить Emacs, над какой ветвью вы работаете. Чтобы сделать так, сначала обратитесь к файлу, затем наберите C-u C-x C-q и укажите правильный номер версии. Это должно гарантировать, что Emacs знает, какая ветвь используется во время конкретного сеанса редактирования.

Снимки

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

Создание и использование снимков

Есть две основные команды для работы со снимками; одна создаёт снимок с заданным именем, а вторая извлекает именованный снимок.

C-x v s имя RET
Определяет последние сохранённые версии каждого зарегистрированного файла в текущем каталоге или ниже него как снимок с заданным именем (vc-create-snapshot).
C-x v r имя RET
Для всех зарегистрированных файлов на уровне текущего каталога или ниже выбирает версии, соответствующие снимку с заданным именем (vc-retrieve-snapshot). Эта команда сообщает об ошибке, если в текущем каталоге или ниже есть заблокированные файлы, и ничего не изменяет; это делается для предотвращения перезаписи редактируемых в данный момент файлов.

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

Вы можете предоставить в качестве аргумента для C-x v = или C-x v ~ имя снимка (смотрите раздел Просмотр и сравнение старых версий). Таким образом, вы можете использовать это для сравнения снимка с текущими файлами, или двух снимков друг с другом или снимка с заданной версией.

Опасные места при работе со снимками

Работа со снимками в VC смоделирована на основе поддежки именованных конфигураций в RCS. Для нее используются встроенные средства RCS, поэтому снимки, сделанные под VC с использованием RCS, видны, даже когда вы обходите VC.

Для SCCS, VC реализует снимки сама. Используемые ей файлы содержат тройки имя/файл/номер-версии. Такие снимки видны только через VC.

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

Переименование и удаление файлов может создать некоторые трудности со снимками. Эта проблема не специфична для VC, но является общим вопросом в реализации систем управления версиями, который никем ещё не решен хорошо.

Если вы переименовываете зарегистрированный файл, вам нужно переименовать и его мастер-файл (команда vc-rename-file делает это автоматически). Если вы пользуетесь SCCS, вы должны также обновить записи о снимках, чтобы они ссылались на этот файл по новому имени (vc-rename-file делает и это тоже). Старый снимок, ссылающийся на мастер-файл, который больше не существует под записанным именем, уже не корректен; VC больше не может извлечь его. Достаточное углубление в подробности об RCS и SCCS для объяснения процесса ручного обновления снимков вышло бы за рамки данного руководства.

Использование vc-rename-file сохраняет корректность снимка для извлечения, но не решает всех проблем. Например, некоторые файлы в программе вероятно ссылаются на другие файлы по именам. По самой меньшей мере, переименованный вами файл упомянут в Make-файле. Если вы извлекаете старый снимок, переименованный файл получает свое новое имя, а не то, которое ожидает Make-файл. Поэтому на самом деле программа не заработает в том виде, в каком её извлекли.

Различные команды и возможности VC

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

Журналы изменений и VC

Если вы используете для программы RCS или CVS и также сопровождаете файл журнала её изменений (смотрите раздел Журналы изменений), вы можете автоматически генерировать вхождения для него из журнальных записей системы управления версиями:

C-x v a
Обращается к журнальному файлу текущего каталога и создаёт для зарегистрированных файлов в этом каталоге новые вхождения для версий, зафиксированных позже последнего вхождения в этом журнальном файле (vc-update-change-log). Эта команда работает только с RCS или CVS, но не с SCCS.
C-u C-x v a
Как выше, но находит вхождения только для файла текущего буфера.
M-1 C-x v a
Как выше, но находит вхождения для всех файлов, к которым вы обращаетесь, и которые сопровождаются системой управления версиями. Это работает только с RCS и также помещает все вхождения в журнал для каталога по умолчанию, что может не подходить.

Для примера предположим, что первая строка в `ChangeLog' датирована 1999-04-10, и что с тех пор случилось только фиксирование, сделанное Натениэлом Боудичем для `rcs2log' 1999-05-22 с журнальной записью `Ignore log messages that start with `#'.'. Тогда C-x v a обращается к `ChangeLog' в вставляет подобный текст:

@medbreak

1999-05-22 Nathaniel Bowditch <nat@apn.org>
 * rcs2log: Ignore log messages that start with `#'.

@medbreak

Теперь вы можете ещё отредактировать новое вхождение в журнал по своему желанию.

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

Обычно вхождение в журнале для файла `foo' отображается как `* foo: текст вхождения'. Знак `:' после `foo' опускается, если текст вхождения начинается со строки `(имя-функции): '. Например, если вхождение для `vc.el' такое: `(vc-do-command): Check call-process status.', то текст в `ChangeLog' выглядит как:

@medbreak

1999-05-06 Nathaniel Bowditch <nat@apn.org>
 * vc.el (vc-do-command): Check call-process status.

@medbreak

Когда C-x v a добавляет несколько вхождений одновременно, она группирует связанные между собой журнальные записи вместе, если все они зафиксированы одним автором примерно в одно время. Если вхождения для нескольких таких файлов имеют одинаковый текст, она объединяет их в одно вхождение. Например, предположим, что последние фиксирования были с такими журнальными записями:

* Для `vc.texinfo': `Fix expansion typos.'
* Для `vc.el': `Don't call expand-file-name.'
* Для `vc-hooks.el': `Don't call expand-file-name.'

В `ChangeLog' они появятся так:

@medbreak

1999-04-01 Nathaniel Bowditch <nat@apn.org>
 * vc.texinfo: Fix expansion typos.
 * vc.el, vc-hooks.el: Don't call expand-file-name.

@medbreak

Обычно C-x v a разделяет журнальные записи пустой строкой, но вы можете сделать так, чтобы несколько связанных записей сцеплялись вместе (без промежуточной пустой строки), начиная текст каждой из связанных журнальных записей с метки в форме `{имя-сцепки} '. Сама метка не копируется в `ChangeLog'. Например, предположим, что есть такие журнальные записи:

* Для `vc.texinfo': `{expand} Fix expansion typos.'
* Для `vc.el': `{expand} Don't call expand-file-name.'
* Для `vc-hooks.el': `{expand} Don't call expand-file-name.'

Тогда текст в `ChangeLog' выглядит так:

@medbreak

1999-04-01 Nathaniel Bowditch <nat@apn.org>
 * vc.texinfo: Fix expansion typos.
 * vc.el, vc-hooks.el: Don't call expand-file-name.

@medbreak

Журнальные записи, чей текст начинается с `#', не копируются в `ChangeLog'. Например, если вы просто поправили грамматические ошибки в комментариях, вы можете сделать в журнале запись, начинающуюся с `#', чтобы в `ChangeLog' не заносились столь тривиальные вещи.

Переименование файлов под VC

Когда вы переименовываете зарегистрированный файл, вы должны переименовать также соответствующий мастер-файл, чтобы получить правильный результат. Используйте vc-rename-file, чтобы переименовать исходный файл, как вы укажете, и соответственно его мастер-файл. Это также обновит все снимки (смотрите раздел Снимки), которые упоминают данный файл, так что они будут использовать новое имя; несмотря на это, измененный таким образом снимок может не работать (смотрите раздел Опасные места при работе со снимками).

Вы не можете использовать vc-rename-file для файла, который блокирован кем-то еще.

Вставка заголовков версий

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

Если вы пользуетесь RCS, и в ваших рабочих файлах присутствуют заголовки версий, Emacs может использовать их для определения текущей версии и состояния блокировки этих файлов. Это более надежно, чем обращение к мастер-файлам, которое делается, если заголовков версий нет. Заметьте, что в среде с несколькими ветвями заголовки версий необходимы для корректной работы VC (смотрите раздел Многопользовательские разветвления).

Переменная vc-consult-headers управляет поиском заголовков версий. Если она отлична от nil, Emacs производит поиск заголовков, чтобы узнать номер версии, которую вы редактируете. Установка этой переменной в nil выключает это средство.

Для вставки подходящей строки заголовка вы можете использовать команду C-x v h (vc-insert-headers).

C-x v h
Вставляет в файл заголовки для использования с вашей системой управления версиями.

Стока заголовка по умолчанию -- это `$Id$' для RCS и `%W%' для SCCS. Вы можете указать другие вставляемые заголовки, устанавливая переменную vc-header-alist. Её значение --- это список элементов в форме (программа . строка), где программа -- это RCS или SCCS, а строка --- это используемая строка.

Вместо одной строки вы можете задать список строк; тогда каждая строка из списка вставится как отдельный заголовок на отдельной строке.

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

Каждый заголовок вставляется в точке на новой строке, в окружении знаков табуляции внутри ограничителей комментария. Как правило, используются обычные для текущего режима строки для начала и завершения комментария, но в некоторых режимах для этой цели есть особые ограничители комметариев; их определяет переменная vc-comment-alist. Каждый элемент в этом списке имеет форму (режим начало конец).

Переменная vc-static-header-alist указывает, какие ещё строки должны добавляться в зависимости от имени буфера. Её значение должно быть списком элементов в форме (regexp . формат). Когда regexp соответствует имени буфера, как часть загловка вставляется формат. Строка загловка вставляется для каждого элемента, совпадающего с именем буфера, и для каждой строки, указанной в vc-header-alist. Строка загловка получается путем форматирования строки из vc-header-alist с форматом, взятым из элемента vc-static-header-alist. По умолчанию vc-static-header-alist имеет следующее значение:

(("\\.c$" .
 "\n#ifndef lint\nstatic char vcid[] = \"\%s\";\n\
#endif /* lint */\n"))

Это определяет вставку текста в такой форме:

#ifndef lint
static char vcid[] = "строка";
#endif /* lint */

Заметьте, что текст выше начинается с пустой строки.

Если вы хотите использовать в файле более одного заголовка версии, помещайте их рядом. Механизм сохранения меток в revert-buffer может не обработать метки, расположенные между двумя заголовками.

Настройка VC

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

Параметры для постпроцессора VC

Вы можете сказать RCS и CVS, должны ли они использовать для файла блокирование или не должны (смотрите раздел Концепции управления версиями, для получения описания блокирования). VC автоматически распознает, что вы выбрали, и ведет себя соответственно.

В RCS по умолчанию применяется блокирование, но есть режим, называемый нестрогим блокированием, в котором вы можете фиксировать изменения без предварительного блокирования файла. Используйте `rcs -U' для переключения к нестрогому блокированию для некоторого файла, подробности смотрите в документе Man `rcs'.

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

С одной стороны, вы можете установить переменную среды `CVSREAD' в произвольное значение. Если эта переменная определена, CVS делает ваши рабочие файлы доступными только для чтения по умолчанию. В Emacs вы должны набрать C-x C-q, чтобы сделать файл доступным для записи, так что редактирование рабочих файлов фактически похоже на редактирование с применением блокирования. Заметьте однако, что фактически блокировки не происходит, поэтому несколько пользователей могут одновременно сделать свои рабочие файлы записываемыми. Когда вы устанавливаете `CVSREAD' первый раз, обязательно заново извлеките все ваши модули, чтобы защита файлов была правильно выставлена.

Другой способ достичь чего-то похожего на блокировку --- воспользоваться средством наблюдения в CVS. Если над файлом установлено наблюдение, CVS по умолчанию делает его доступным только для чтения, и вы также должны использовать в Emacs C-x C-q, чтобы сделать его записываемым. Чтобы сделать файл доступным для записи, VC вызывает cvs edit, и CVS заботится о том, чтобы другие разработчики были оповещены о вашем намерении изменить этот файл. Подробности об использовании средства наблюдения смотрите в документации по CVS.

Вы можете подавить использование VC для файлов, управляемых CVS, установив переменную vc-handle-cvs в nil. Если вы сделаете так, Emacs считает эти файлы незарегистритованными, и команды VC становятся в них недоступными. Тогда вы должны делать все операции CVS вручную.

Управление рабочими файлам в VC

Обычно Emacs не сохраняет резервные копии для исходных файлов, которые находятся под контролем системы управления версиями. Если вы хотите делать резервные копии даже для таких файлов, установите переменную vc-make-backup-files в отличное от nil значение.

Как правило рабочие файлы существуют всегда, блокированы они или нет. Если вы установите vc-keep-workfiles в nil, то при фиксировании новой версии с помощью C-x C-q рабочий файл будет удаляться; но любая попытка обратиться к этому файлу из Emacs создаст его снова. (Под CVS рабочие файлы остаются всегда.)

Редактирование файла в управлением версиями через символьную ссылку может быть опасным. Это обходит систему управления версиями -- вы можете редактировать файлы, не блокируя их, и у вас может не получиться зафиксировать свои изменения. Также, ваши изменения могут перезаписать версию другого пользователя. Чтобы предоставить защиту от этого, VC проверяет каждую символьную ссылку, к которой вы обращаетсь, чтобы узнать, не указывает ли она на файл под контролем системы управления версиями.

Переменная vc-follow-symlinks говорит, что нужно делать, когда символьная ссылка указывает на файл с управлением версиями. Если она равна nil, VC лишь показывает предупреждающее сообщение. Если это t, VC автоматически следует по ссылке и обращается к настоящему файлу, сообщая вам об этом в эхо-области. Если это значение равно ask (по умолчанию), VC всякий раз спрашивает вас, нужно ли проследовать по ссылке.

Как VC узнает статус файла

При вычислении статуса блокировки файла, VC сначала ищет в нём строку заголовка версии RCS (смотрите раздел Вставка заголовков версий). Если строки заголовка нет, или если вы пользуетесь SCCS, VC обычно смотрит на разрешения, установленные для рабочего файла; это быстро. Но могут быть ситуации, когда разрешениям нельзя доверять. В таком случае делается обращение к мастер-файлу, что довольно дорого. Кроме того, мастер-файл может только сказать, заблокирован ли файл кем-то, но не то, что ваш рабочий файл содержит именно эту блокированную версию.

Вы можете указать VC не использовать заголовки версии для определения статуса блокировки, установив vc-consult-headers в nil. Тогда VC всегда использует для этого биты разрешений для файла (если она может им доверять) или проверяет мастер-файл.

Вы можете задать критерий, по которому следует доверять разрешениям для файла, с помощью переменной vc-mistrust-permissions. Её значением может быть t (никогда не доверять битам разрешений и всегда проверять мастер-файл), nil (всегда доверять разрешениям) или функция с одним аргументом, которая принимает решение. Аргумент --- это имя подкаталога `RCS', `CVS' или `SCCS'. Отличное от nil значение из этой функции говорит, что битам разрешений доверять нельзя. Если вы обнаружили, что разрешения для рабочего файла выстановлены ошибочно, установите vc-mistrust-permissions в t. Тогда VC всегда будет проверять мастер-файл для определения статуса файла.

Выполнение команд в VC

Если vc-suppress-confirm отлична от nil, то C-x C-q и C-x v i могут сохранять текущий буфер без запроса, и C-x v u также работает без подтверждения. (Эта переменная не влияет на C-x v c; данная операция насколько значительна, что для нее всегда нужно спрашивать подтверждение.)

Режим VC делает большую часть работы, запуская команды оболочки для RCS, CVS и SCCS. Если vc-command-messages отлична от nil, VC выводит сообщения, показывающие, какие команды оболочки запускаются, и дополнительные сообщения, когда команда завершается.

Вы можете задать дополнительные каталоги для поиска программ управления версиями, устанавливая переменную vc-path. Эти каталоги просматриваются перед обычным путем поиска. Но обычно правильные файлы находятся автоматически.

Каталоги файлов

Файловая система группирует файлы по каталогам. Распечатка каталога -- это список всех файлов в каталоге. Emacs предоставляет команды для создания и удаления каталогов и для выдачи распечатки каталогов в кратком формате (только имена файлов) и в подробном формате (включающем размеры, даты и авторов). Есть также броузер каталогов, называемый Dired; смотрите раздел Dired, редактор каталогов.

C-x C-d кат-или-образец RET
Выводит краткую распечатку каталога (list-directory).
C-u C-x C-d кат-или-образец RET
Выводит подробную распечатку каталога.
M-x make-directory RET имя-кат RET
Создает новый каталог с именем имя-кат.
M-x delete-directory RET имя-кат RET
Удаляет каталог с именем имя-кат. Он должен быть пуст, иначе вы получите ошибку.

Команда для вывода распечатки каталога -- это C-x C-d (list-directory). Она считывает, используя минибуфер, имя файла, который является либо каталогом, который нужно распечатать, либо шаблоном имён файлов, которые нужно перечислить. Например,

C-x C-d /u2/emacs/etc RET

перечисляет все файлы в каталоге `/u2/emacs/etc'. Вот пример описания образца имён файлов:

C-x C-d /u2/emacs/src/*.c RET

Обычно C-x C-d печатает краткий перечень каталога, содержащий только имена файлов. Числовой аргумент (независимо от значения) велит показывать подробную распечатку (как `ls -l').

Текст распечатки каталога получается от ls, запущенной в подчиненном процессе. Две переменные Emacs управляют ключами, передаваемыми ls: list-directory-brief-switches -- это строка, дающая ключи для использования в кратких распечатках ("-CF" по умолчанию), и list-directory-verbose-switches --- ключи для подробной распечатки ("-l" по умолчанию).

Сравнение файлов

Команда M-x diff сравнивает два файла, показывая различия в буфере Emacs с именем `*Diff*'. Она запускает программу diff, используя ключи, получаемые из переменной diff-switches, чье значение должно быть строкой.

Буфер `*Diff*' имеет в качестве основного режим Compilation, поэтому вы можете использовать C-x `, чтобы последовательно обратиться к изменившимся местам в двух исходных файлах. Вы также можете перейти к конкретному ломтю изменений и нажать RET или C-c C-c, или щёлкнуть на нём Mouse-2, чтобы перейти к соответствующей позиции в исходном тексте. Вы также можете использовать другие особые команды режима Compilation: SPC и DEL для прокрутки и M-p и M-n для передвижения курсора. Смотрите раздел Запуск компиляторов в Emacs.

Команда M-x diff-backup сравнивает заданный файл с его самой последней резервной копией. Если вы задали имя резервного файла, diff-backup сравнивает его с исходным файлом.

Команда M-x compare-windows сравнивает текст в текущем окне с текстом следующего окна. Сравнение начинается от точки в каждом окне, и обе начальные позиции вталкиваются в список пометок соответствующего буфера. Затем точка перемещается в каждом окне вперёд по одному знаку, пока не будет найдено несовпадение. Тогда эта команда останавливается. Для получения большей информации об окнах в Emacs смотрите раздел Множество окон.

С числовым аргументом, compare-windows игнорирует изменения в пропусках. Если переменная compare-ignore-case не nil, она игнорирует также и различия в регистре букв.

Смотрите также раздел Объединение файлов с помощью Emerge, описание удобных средств для слияния двух похожих файлов.

Разнообразные действия над файлами

В Emacs есть команды для произведения многих других операций над файлами. Все они действуют на один файл; они не воспринимают имена файлов с шаблонами.

M-x view-file позволяет вам просмотреть или прочитать файл по целым экранам. Она считывает имя файла, используя минибуфер. После загрузки файла в буфер Emacs, view-file показывает его начало. Теперь вы можете нажать SPC, чтобы прокрутить вперёд на целое окно, или DEL для прокрутки назад. Предоставляются и другие различные команды для перемещения по файлу, но не для его изменения; наберите во время просмотра ?, чтобы получить их перечень. Это практически те же обычные команды Emacs для передвижения курсора. Чтобы выйти из просмотра, наберите q. Команды просмотра определяются особым основным режимом, называемом режимом View.

Есть родственная команда, M-x view-buffer, для просмотра буфера, уже существующего в Emacs. Смотрите раздел Разнообразные операции над буфером.

M-x insert-file вставляет копию содержимого заданного файла в текущий буфер в позиции точки, оставляя точку неизменной перед вставленным и метку после него.

M-x write-region -- это обращение M-x insert-file; она копирует содержимое области в указанный файл. M-x append-to-file добавляет текст области в конец заданного файла. Смотрите раздел Накопление текста.

M-x delete-file удаляет указанный файл, как команда оболочки rm. Если вы хотите удалить много файлов в одном каталоге, может оказаться удобнее воспользоваться Dired (смотрите раздел Dired, редактор каталогов).

M-x rename-file считывает, используя минибуфер, два имени файла, старый и новый, а затем переименоывает файл старый в новый. Если файл с именем новый уже существует, вы должны подтвердить переименование вводом yes, или переименование не производится; это сделано, потому что такое переименование приведет к потере старого значения имени новый. Если старый и новый находятся на разных файловых системах, файл старый копируется и удаляется.

Похожая команда M-x add-name-to-file используется для добавления ещё одного имени существующему файлу без удаления старого имени. Новое имя обязано принадлежять той же файловой системе, где находится сам файл.

M-x copy-file считывает файл старый и записывает новый файл с именем новый с тем же содержимым. Если файл с именем новый уже существует, требуется подтверждение, потому что копирование затирает старое содержимое файла новый.

M-x make-symbolic-link считывает два имени файла, цель и имя-ссылки, а затем создаёт символьную ссылку с именем имя-ссылки, указывающую на цель. Это проявится в том, что будущие попытки открыть файл имя-ссылки получат тот файл, который называется цель во время открытия, или получат ошибку, если имя цель в это время не используется. Эта команда не раскрывает аргумент цель, поэтому она позволяет вам указать относительное имя в качестве файла назначения ссылки.

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

Доступ к сжатым файлам

Emacs поставляется с библиотекой, которая автоматически распаковывает сжатые файлы, когда вы к ним обращаетесь, и автоматически сжимает их снова, если вы их изменили и сохраняете. Чтобы задействовать эту возможность, наберите команду M-x auto-compression-mode.

Когда включено автоматическое сжатие (что подразумевает и автоматическую распаковку), Emacs распознаёт сжатые файлы по именам. Имена файлов, завершающиеся на `.gz', указывают, что этот файл сжат программой gzip. Другие окончания обозначают другие методы сжатия.

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

Удаленные файлы

Вы можете сослаться на файлы на других машинах, используя особый синтаксис имён:

/машина:имя-файла
/пользователь@машина:имя-файла

Когда вы делаете так, Emacs использует для чтения и записи файлов на указанной машине программу FTP. Он заходит через FTP, используя ваше пользовательское имя или имя пользователь. Он может спрашивать у вас пароль время от времени; это используется для захода на машину.

Обычно, если вы не задали имя пользователя в имени удалённого файла, это означает, что нужно использовать ваше собственное пользовательское имя. Но если вы установите переменную ange-ftp-default-user равной какой-то строке, то будет использоваться эта строка. (Пакет Emacs, который реализует доступ к файлам по FTP, называется ange-ftp.)

Вы можете полностью выключить обработку имён FTP-файлов, установив переменную file-name-handler-alist в значение nil.

Буквальные имена файлов

Вы можете отменить особый смысл абсолютного имени файла, чтобы блокировать действие специальных символов и синтаксиса. Это можно сделать, добавив `/:' в начале.

Например, вы можете отменить особый смысл имени локального файла, который выглядит как удалённый, чтобы предотвратить его трактовку как имени удалённого файла. Таким образом, если у вас есть каталог с именем `/foo:' и в нём файл с именем `bar', вы можете сослаться в Emacs на этот файл как на `/:/foo:/bar'.

`/:' также может предотвратить понимание `~' как специального символа, обозначающего начальный каталог этого пользователя. Например, `/:/tmp/~hack' ссылается на файл с именем `~hack' в каталоге `/tmp'.

Аналогично, использование `/:' -- это один из способов ввести в минибуфере имя файла, содержащее `$'. Однако, `/:' обязана быть в начале этого буфера, чтобы блокировать эффект `$'.

С помощью `/:' вы также можете подавить эффект символов подстановки при обращении к файлам. Например, `/:/tmp/foo*bar' обращается к файлу `/tmp/foo*bar'. Однако, чаще всего вы просто можете ввести символы подстановки как есть. Например, если единственное имя файла в `/tmp', которое начинается на `foo' и завершается на `bar' -- это `foo*bar', то указав `/tmp/foo*bar' вы обратитесь только к `/tmp/foo*bar'.

Назад |  Вперед |  Содержание



Распространение материалов сайта означает, что распространитель принял условия лицензионного соглашения.
Идея и реализация: © Владимир Довыденков и Анатолий Камынин,  2004-2024