Добавить в избранное | Сделать стартовой страницей

Большая Linux библиотека для пользователей OS Linux и ПО для нее
Есть что сказать? Нужен совет? Посети наш форум.




Руководство по GNU Emacs. часть 3

Управление изображением

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

Прокрутка

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

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

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

C-l
Очистить экран и восстановить изображение, сдвигая по вертикали выбранное окно к центральной точке в пределах окна (recenter).
C-v
NEXT
Прокрутить вперед (на одно окно или на определенное число строк) (scroll-up).
M-v
PRIOR
Прокрутить назад (scroll-down).
арг C-l
Прокрутить таким образом, что точка оказывается на строке арг (recenter).
C-M-l
Прокрутить эвристически, чтобы вывести на экран полезную информацию (reposition-window).

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

Команды прокрутки C-v и M-v позволяют вам двигать весь текст в окне вверх или вниз на несколько строк. C-v (scroll-up) с аргументом показывает вам заданное количество строк, находящихся за нижней границей окна, сдвигая текст и точку вверх вместе, как C-l. C-v с отрицательным аргументом показывает вам больше строк, находящихся за верхней границей окна. M-v (scroll-down) подобна C-v, но двигает в обратном направлении. Функциональные клавиши NEXT и PRIOR эквивалентны C-v и M-v.

Имена команд прокрутки основаны на направлении, в котором движется текст в окне. Таким образом, команда прокрутки вперед называется scroll-up, потому что она перемещает текст вверх по экрану.

Чтобы прочитать буфер по целому окну, используйте C-v без аргумента. Эта команда берет последние две строки, находящиеся внизу окна, и ставит их в начало, и за ними далее следует почти все окно строк, невидимых ранее. Если точка находилась в тексте, ушедшем за верхний край окна, то она передвигается в новую вершину окна. M-v без аргумента двигает текст в обратном направлении с аналогичным перекрыванием. Количество перекрывающихся строк при C-v или M-v управляется переменной next-screen-context-line, по умолчанию оно равно двум.

Некоторым пользователям нравится, когда команды прокрутки всего окна сохраняют точку на одной строке экрана. Чтобы включить такое поведение, установите переменную scroll-preserve-screen-position не равной nil. Такой режим удобен для просмотра файлов путем прокрутки по целому экрану; если вы вернетесь на экран, с которого начали, точка вернется на начальную строку. Однако, этот режим неудобен, когда вы перемещаетесь на следующий экран, чтобы передвинуть туда точку.

Другой способ выполнить прокрутку -- использовать команду C-l с числовым аргументом. C-l с заданным аргументом не очищает экран, она только прокручивает выбранное окно. С положительным аргументом n она перемещает текст так, чтобы установить точку на n строк вниз от вершины. Аргумент, равный нулю, устанавливает точку на самую верхнюю строку. Точка не двигается по отношению к тексту; скорее, текст и точка двигаются на экране жестко связанные вместе. C-l с отрицательным аргументом устанавливает точку на заданное число строк выше от конца окна. Например, C-u - 1 C-l устанавливает точку на нижней строке, а C-u - 5 C-l устанавливает ее на пять строк выше конца окна. Просто C-u в качестве аргумента в C-u C-l прокручивает точку к центру экрана.

Команда C-M-l (reposition-window) прокручивает текущее окно эвристически, так, чтобы вывести на экран полезную информацию. Например, в файле с программой на Лиспе эта команда пытается разместить на экране все текущее определение функции, если это возможно.

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

Переменная scroll-margin определяет, насколько близко может подойти точка к вершине или к низу окна. Ее значение -- это число экранных строк; если точка подходит на заданное число строк к вершине или к низу окна, Emacs заново центрирует это окно. По умолчанию scroll-margin равна 0.

Горизонтальная прокрутка

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

C-x <
Прокручивает текст текущего окна влево (scroll-left).
C-x >
Прокручивает вправо (scroll-right).

Когда окно прокручивается по горизонтали, строки текста становятся усеченными, а не продолженными. (смотрите раздел Строки продолжения); знак `$' появляется в первом столбце, если есть текст, усеченный слева, и в последнем столбце, если существует текст, усеченный справа.

Команда C-x < (scroll-left) с аргументом n прокручивает выбранное окно влево на n столбцов. Она перемещает часть начала каждой строки за левый край окна. Без аргумента, она прокручивает почти на полную ширину окна (без двух столбцов, если быть точным).

C-x > (scroll-right) прокручивает аналогично, но только вправо. Окно не может быть прокручено дальше вправо, если оно отображено нормально (каждая строка начинается с левого края окна). Попытка сделать это не будет иметь результата. Это значит, что вы не обязаны точно вычислять аргумент для C-x >; любое достаточное большое число восстановит нормальное изображение.

Вы можете потребовать автоматической горизонтальной прокрутки, включив режим Hscroll. Когда этот режим задействован, Emacs горизонтально прокручивает окно всякий раз, когда это необходимо для сохранения точки видимой и расположенной не слишком далеко от левого или правого края. Команда для включения и выключения этого режима -- M-x hscroll-mode.

Режим Follow

Режим Follow -- это второстепенный режим, который делает так, что два окна, показывающие один и тот же буфер, прокручиваются как одно большое "виртуальное окно". Чтобы использовать режим Follow, перейдите во фрейм с одним окном, разбейте его на два примыкающих окна с помощью C-x 3 и затем напечатайте M-x follow-mode. Теперь вы можете редактировать буфер в любом из двух окон или прокручивать любое из них; второе окно будет следовать изменениям.

Чтобы выключить режим Follow, напечатайте M-x follow-mode второй раз.

Выборочный показ

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

Чтобы спрятать строки, наберите C-x $ (set-selective-display) с числовым аргументом n. После этого строки, имеющие по крайней мере n столбцов отступа, пропадут с экрана. Показателем их существования являются только три точки (`...'), появляющиеся в конце каждой видимой строки, за которой следует одна или более невидимых.

Команды C-n и C-p перемещаются сквозь спрятанные строки, как если бы их не было.

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

Чтобы сделать всё видимым снова, наберите C-x $ без аргумента.

Если вы установите переменную selective-display-ellipses равной nil, то три точки не будут появляться в конце строки, которая предшествует спрятанным строкам. Тогда не будет никакого видимого указания на наличие скрытых строк. Эта переменная при установке автоматически становится локальной.

Дополнительные возможности строки режима

Когда включен режим Line Number, в строке режима появляется номер текущей строки, где находится точка. Используйте для переключения этого режима команду M-x line-number-mode; обычно он включен. Номер строки появляется перед поз, позицией в процентах от объема буфера, с буквой `L' для указания на то, что это такое. Смотрите раздел Второстепенные режимы, для дальнейшей информации о второстепенных режимах и о том, как применять эту команду.

Если буфер очень большой (больше, чем значение переменной line-number-display-limit), то номер строки не выводится. Emacs не подсчитывает номера строк, если буфер велик, потому что это было бы слишком медленно. Если вы сузили буфер (смотрите раздел Сужение), отображаемый номер строки отчитывается относительно доступной части буфера.

Вы также можете показать номер текущего столбца, включив режим Column Number. Он отображает номер текущего столбца после буквы `C'. Для переключения этого режима напечатайте M-x column-number-mode.

Emacs может показывать время и загрузку системы во всех строках режима. Чтобы задействовать эту возможность, напечатайте M-x display-time. Эти сведения, добавляемые к строке режима, обычно появляются после имени буфера перед именами режимов. Это выглядит так:

чч:ммpm з.зз

Здесь чч и мм обозначают часы и минуты, за которыми всегда следуют `am' или `pm'. з.зз -- это среднее число процессов, запущенных во всей системе. (Некоторые поля могут быть пропущены, если ваша операционная система не поддерживает их.) Если вы предпочитаете видеть время в двадцатичетырехчасовом формате, установите переменную display-time-24hr-format в значение t.

Если для вас есть почта, которую вы еще не читали, после уровня загрузки появляется слово `Mail'.

Как отображается текст

Печатные знаки ASCII (с восьмиричными кодами от 040 до 0176) отображаются в буферах Emacs как их собственные графические представления. То же и для многобайтных печатных знаков, не входящих в ASCII (с восьмиричными кодами выше 0400).

Некоторые управляющие знаки ASCII отображаются особым образом. Знак новой строки (восьмиричный код 012) отображается как начало новой строки. Знак табуляции (восьмиричный код 011) показывается продвижением до следующей позиции табуляции (обычно через каждые 8 столбцов).

Другие управляющие знаки ASCII обычно отображается как шапочка (`^'), за которой следует неуправляющая версия знака; таким образом, control-A показывается как `^A'.

Не-ASCII-знаки от 0200 до 0377 отображаются с помощью восьмиричных управляющих последовательностей; например, знак с кодом 0243 (восьмиричным) выводится как `\243'. Однако, если вы включите отображение европейских алфавитов, то большинство этих знаков станут печатными не-ASCII-знаками и будут отображаться с использованием их графических представлений (в предположении, что ваш терминал поддерживает это). Смотрите раздел Поддержка однобайтных европейских знаков.

Переменные управления изображением

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

Переменная mode-line-inverse-video управляет тем, отражается ли строка режима в инверсном виде (в предположении, что терминал поддерживает это); nil значит, что это не делается. Смотрите раздел Строка режима. Если вы зададите цвет шрифта для начертания modeline, и mode-line-inverse-video не равна nil, то по умолчанию цветом фона для этого начертания будет цвет простого текста. Смотрите раздел Использование разных начертаний.

Если переменная inverse-video не равна nil, Emacs пытается инвертировать все строки дисплея из их обычного состояния.

Если переменная visible-bell не nil, Emacs пытается мерцать экраном, когда обычно он подает звуковой сигнал. Эта переменная не действует, если ваш терминал не умеет мерцать экраном.

Когда вы снова входите в Emacs после прерывания, Emacs обычно очищает экран и перерисовывает все изображение. На некоторых терминалах, имеющих более одной страницы памяти, можно сделать такую запись termcap, чтобы строки `ti' и `te' (выводимые терминалу, когда в Emacs входят и выходят, соответственно) переключали страницы памяти так, чтобы использовать одну для Emacs, а вторую для другого вывода. Затем, вы можете по желанию установить переменную no-redraw-on-reenter не равной nil; это велит Emacs предполагать, что страница экрана после повторного входа все еще содержит то, что Emacs туда записал в последний раз.

Переменная echo-keystrokes управляет отражением многознаковых ключей. Значение этой переменной -- это выраженная в секундах длина паузы, требуемой для вызова эхо; если оно равно нулю, это значит, что эхо не будет. Смотрите раздел Эхо-область.

Если переменная ctl-arrow равна nil, то управляющие знак будут показаны в буфере с помощью восьмиричных управляющих последовательностей, все, кроме ограничителя новой строки и табуляции. Изменение значения переменной ctl-arrow делает ее локальной для текущего буфера, до этого же момента действует значение по умолчанию. Значение по умолчанию равно t. Смотрите раздел `Display Tables' в The Emacs Lisp Reference Manual.

Обычно знак табуляции показывается в буфере как пробел, который простирается до следующей позиции табуляции дисплея; остановки по табуляции происходят через интервал, равный восьми пробелам. Число пробелов в табуляции управляется переменной tab-width, которая становится локальной при ее изменении, так же, как и ctl-arrow. Отметим, что способ отображения символа табуляции в буфере никак не влияет на определение TAB, как команды. Переменная tab-width должна иметь значение между 1 и 1000, включительно.

Если переменная truncate-lines не равна nil, то каждая строка текста занимает ровно одну строку на экране; если строка текста слишком длинна, показывается только умещающаяся часть. Если truncate-lines равна nil, то длинные строки текста отображаются как несколько строк на экране, столько, сколько нужно, чтобы показать весь текст строки. Смотрите раздел Строки продолжения. Изменение значения truncate-lines делает ее локальной для текущего буфера; до этого момента действует значение по умолчанию. Это значение по умолчанию изначально равно nil.

Если переменная truncate-partial-width-windows не равна nil, она принуждает усечение длинных строк вместо их продолжения в любом окне уже полной ширины фрейма, несмотря на значение переменной truncate-lines. Для получения информации о примыкающих окнах, смотрите раздел Разделение окон. Смотрите также раздел `Display' в The Emacs Lisp Reference Manual.

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

Вы можете настроить способ вывода каждого конкретного знака с помощью таблицы отображения. Смотрите раздел `Display Tables' в The Emacs Lisp Reference Manual.

Поиск и замена

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

Кроме обычной команды replace-string, которая находит все случаи появления одной строки и заменяет их другой, Emacs имеет более сложную команду замены, названную query-replace, которая запрашивает в интерактивном режиме, в каких случаях надо произвести замену.

Наращиваемый поиск

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

C-s
Наращиваемый поиск вперед (isearch-forward).
C-r
Наращиваемый поиск в обратном направлении (isearch-backward).

C-s начинает наращиваемый поиск. C-s считывает знаки с клавиатуры и располагает курсор в первом месте появления знаков, которые вы набрали. Если вы наберете C-s и затем F, то курсор встанет справа после первой найденной `F'. Наберите О, и увидите, что курсор встал за первой найденной `FO'. После еще одной О курсор встанет за первой `FOO', находящейся за местом, с которого вы начали поиск. На каждом шаге текст буфера, совпадающий со строкой поиска, подсвечивается, если терминал может это сделать; текущая строка поиска обновляется на каждом шаге в эхо-области.

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

Когда вы будете удовлетворены достигнутым местом, вы можете набрать RET, что остановит поиск, оставляя курсор там, куда его поместила команда поиска. Любая команда, не имеющая специального значения при поиске, также останавливает поиск и затем выполняется сама. Таким образом, набор C-a привел бы к выходу из поиска и затем передвинул бы курсор в начало строки. RET необходим только в том случае, если следующая команда, которую вы хотите набрать, является печатным знаком, DEL, RET или другим управляющим знаком, имеющим особое значение во время работы поиска (C-q, C-w, C-r, C-s, C-y, M-y, M-r или M-s).

Иногда вы ищете слово `FOO' и находите его, но это не то, что вам нужно. Было второе `FOO', о котором вы забыли, находящееся перед тем, которое вы ищете. В этом случае наберите C-s еще раз, чтобы продвинуться к следующему появлению строки поиска. Это можно проделывать неограниченное число раз. Если вы проскочили, то можете отменить некоторые число знаков C-s с помощью DEL.

После выхода из поиска вы можете снова искать ту же самую строку, просто набрав C-s C-s: первый C-s -- это ключ, который запускает наращиваемый поиск, а второй C-s означает "повтор поиска".

Чтобы вы могли снова использовать более ранние строки поиска, существует список поиска. Команды M-p и M-n передвигают по списку, чтобы вы могли подобрать нужную строку для повторного поиска. Эти команды оставляют выбранную строку поиска в минибуфере, где вы можете ее отредактировать. Для завершения редактирования и начала поиска наберите C-s или C-r.

Если ваша строка вообще не найдена, то эхо-область говорит `Failing I-Search'. Курсор располагается после того места, где Emacs нашел из вашей строки всё, что смог. Таким образом, если вы ищете `FOOT', а такой строки нет, вы можете увидеть курсор после `FOO' в слове `FOOL'. С этого места вы можете сделать несколько вещей. Если ваша строка неправильно набрана, вы можете что-то стереть из нее и исправить. Если вы довольны найденным местом, вы можете набрать RET или любую другую команду Emacs, чтобы "принять то, что предложил этот поиск", или вы можете набрать C-g, что уничтожит из строки поиска знаки, которые не были найдены (`Т' в `FOOT'), оставляя те, что нашлись (`FOO' в `FOOT'). Второй C-g в этом месте отменяет поиск полностью, возвращая точку туда, где она была, когда поиск начался.

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

Если поиск был неудачным и вы просите повторить его, набирая C-s еще раз, то он начинается снова с начала буфера. Повторение неудачного поиска в обратном направлении при помощи команды C-r начинает новый поиск с конца. Такой поиск называется круговым. Как только это произошло, в подсказке поиска появляется слово `Wrapped'. Если вы пройдете через точку, где начался поиск, это слово заменяется на `Overwrapped', что означает, что вы снова проходите через уже виденные вами совпадения.

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

Чтобы найти символ перевода строки, введите C-j. Для поиска другого управляющего знака, такого как control-S или возврат каретки, вы должны отменить их специальное значение, набирая перед ними C-q. Эта функция C-q аналогична ее назначению как команды для вставки (смотрите раздел Вставка текста): она заставляет трактовать следующий знак так, как в этом контексте трактовался бы любой "обычный" знак. Вы также можете задать знак по его восьмиричному коду: введите C-q и затем последовательность восьмиричных цифр.

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

Если вы заранее знаете, что вам нужно вести поиск в обратном порядке, то чтобы начать поиск, вы можете использовать C-r вместо C-s, так как C-r также является ключом, запускающим команду (isearch-backward) для поиска в обратном порядке. Обратный поиск находит совпадения, которые расположены перед начальной точкой, так же как поиск вперед находит совпадения, начинающиеся после точки, где поиск начался.

Знаки C-y и C-w могут использоваться в наращиваемом поиске для захвата текста из буфера в строку поиска. Это делает удобным поиск другого случая появления того текста, который находится в точке. C-w копирует слово после точки в строку поиска, продвигая точку вперед через это слово. Следующая команда C-s для повторения поиска будет затем искать строку, включающую это слово. C-y подобна C-w, только копирует в строку поиска весь остаток текущей строки. И C-y, и C-w преобразуют копируемый текст к нижнему регистру, если поиск сейчас ведется без учета регистра; таким образом поиск остается регистронезависимым.

Команда M-y копирует в строку поиска текст из списка уничтожений. Она использует тот же текст, который был бы восстановлен командой C-y. Смотрите раздел Восстановление.

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

Чтобы настроить специальные знаки, которые понимает наращиваемый поиск, измените их привязки в таблице ключей isearch-mode-map. Для получения перечня привязок посмотрите документацию на isearch-mode с помощью C-h f isearch-mode RET.

Наращиваемый поиск на медленном терминале

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

Когда вы прерываете поиск, однострочное окно убирается. Только в этот момент Emacs перерисовывает окно, в котором производился поиск, чтобы отобразить новое положение точки.

Такой стиль отображения используется, когда скорость терминала в бодах меньше или равна значению переменной search-slow-speed, чье начальное значение равно 1200.

Количество строк, показываемых при поиске на медленном терминале, управляется переменной search-slow-window-lines. Ее обычное значение равно единице.

Ненаращиваемый поиск

В Emacs также есть удобные команды ненаращиваемого поиска, которые требуют от вас полностью набрать строку поиска до начала работы.

C-s RET строка RET
Поиск заданной строки.
C-r RET строка RET
Поиск строки в обратном направлении.

Чтобы начать ненаращиваемый поиск, наберите сначала C-s RET. Эта команда входит в минибуфер для считывания строки поиска; ограничьте эту строку с помощью RET, и поиск начнется. Если строка не будет найдена, команда поиска выдает ошибку.

Способ работы C-s RET заключается в следующем: C-s запускает наращиваемый поиск, который специально запрограммирован так, что запускает ненаращиваемый поиск, если заданный вами аргумент является пустым. (Такой пустой аргумент в других случаях был бы бесполезен). C-r RET работает аналогично.

Однако, запрошенный с помощью C-s RET ненаращиваемый поиск не запускает непосредственно search-forward. Первым делом проверяется, не будет ли следующим знаком C-w, что запустит поиск слов.

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

Поиск слов

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

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

C-s RET C-w слова RET
Ищет слова, игнорируя пунктуацию между ними.
C-r RET C-w слова RET
Ищет слова в обратном направлении, игнорируя пунктуацию между ними.

Поиск слов -- это специальный случай ненаращиваемого поиска, и он вызывается с помощью C-s RET C-w. За этим следует строка поиска, которая всегда должна быть ограничена RET. Будучи ненаращиваемым, поиск не начинается до тех пор, пока аргумент не завершен. Этот поиск работает путем создания регулярного выражения и его поиска; смотрите раздел Поиск регулярного выражения.

Для обратного поиска слов используйте C-r RET C-w.

Прямой и обратный поиск слов реализован в командах word-search-forward и word-search-backward. Эти команды могут быть привязаны к ключам обычным способом. Возможность их запуска через наращиваемый поиск существует по историческим причинам и для того, чтобы вам не нужно было находить для них подходящие последовательности ключей.

Поиск регулярного выражения

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

Наращиваемый поиск регулярного выражения производится набором C-M-s (isearch-forward-regexp). Эта команда считывает наращиваемую строку поиска, так же, как C-s, но трактует ее как регулярное выражение, а не ищет в тексте буфера точное совпадение. Каждый раз, когда вы добавляете текст в строку поиска, вы делаете регулярное выражение длиннее, и ищется уже новое регулярное выражение. Вызов C-s с префиксным аргументом (значение не играет роли) --- это другой способ произвести прямой поиск регулярного выражения. Чтобы запустить поиск регулярного выражения в обратном направлении, используйте C-M-r (isearch-backward-regexp) или C-r с префиксным аргументом.

Все управляющие знаки, которые делают специальные вещи в рамках обыкновенного наращиваемого поиска, имеют те же самые функции и в наращиваемом поиске регулярного выражения. Набор C-s или C-r немедленно после начала поиска восстанавливает последнее регулярное выражение, использованное для наращиваемого поиска регулярного выражения; это говорит о том, что наращиваемый поиск регулярного выражения и строки имеют независимые значения по умолчанию. Они также имеют раздельные списки поиска, доступ к которым вы можете получить с помощью M-p и M-n.

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

Обратите внимание, добавление знаков к регулярному выражению при наращиваемом поиске может вернуть курсор назад и начать поиск снова. Например, если вы искали `foo' и добавляете `\|bar', курсор вернется назад, если первый `bar' предшествовал первому `foo'.

Ненаращиваемый поиск регулярного выражения осуществляется функциями re-search-forward и re-search-backward. Вы можете запустить их с помощью M-x, или привязать их к ключам или вызывать через наращиваемый поиск регулярного выражения с помощью C-M-s RET и C-M-r RET.

Если вы используете команды наращиваемого поиска регулярного выражения с префиксным аргументом, они производят обычный поиск строки, как isearch-forward и isearch-backward. Смотрите раздел Наращиваемый поиск.

Синтаксис регулярных выражений

Регулярные выражения имеют синтаксис, в котором несколько знаков служат специальными конструкциями, а остальные -- это обыкновенные знаки. Обыкновенный знак -- это простое регулярное выражение, которое соответствует этому знаку и никакому больше. Специальными знаками являются `$', `^', `.', `*', `+', `?', `[', `]' и `\'. Любые другие знаки, появляющиеся в регулярном выражении, являются обыкновенными, если только им не предшествует `\'.

Например, `f' -- это неспециальный знак, значит он обыкновенный, поэтому `f' -- это регулярное выражение, которое соответствует строке `f' и никакой другой. (Оно не соответствует строке `ff'). Аналогично, `о' -- это регулярное выражение, которое соответствует только `о'. (Когда различия в регистре игнорируются, эти регулярные выражения также совпадают с `F' и `O', но мы рассматриваем это как обобщение понятия "та же строка", а не как исключение.)

Любые два регулярных выражения a и b могут быть сцеплены. Результатом является регулярное выражение, совпадающее со строкой, в которой a соответствует некоторому началу этой строки, а b соответствует остатку строки.

В качестве простого примера мы можем сцепить регулярные выражения `f' и `o', чтобы получить регулярное выражение `fo', которое соответствует только строке `fo'. Пока все просто. Чтобы сделать что-то нетривиальное, вам необходимо использовать один из специальных знаков. Здесь представлен их перечень.

. (Точка)
является специальным знаком, который соответствует любому одиночному знаку, за исключением перевода строки. Используя конкатенацию (сцепление), вы можете составить регулярное выражение, подобное `a.b', которое соответствует любой трехзнаковой строке, начинающейся с `a' и кончающейся на `b'.
*
сама по себе не является конструкцией; это постфиксный оператор, который означает, что предыдущее регулярное выражение должно быть повторено столько раз, сколько это возможно. Таким образом, `o*' соответствует любому числу букв `o' (включая нуль). `*' всегда относится к наименьшему возможному предыдущему выражению. Таким образом, `fo*' содержит повторяющуюся `о', а не `fo'. Оно совпадает с `f', `fo', `foo' и так далее. Конструкция `*' обрабатывается путем сопоставления с наибольшим количеством повторений, которое сразу может быть найдено. Затем продолжается сравнение с остатком шаблона. Если оно прошло неудачно, то происходит перебор с возвратом. Некоторые из совпадений с конструкцией с модификатором `*' сбрасываются, чтобы дать возможность поиска соответствия для остатка структуры. Например, сравнивая `ca*ar' со строкой `caaar', `a*' сначала ставится в соответствие со всеми тремя `а', но остаток шаблона -- это `ar', а в этом случае для подбора остается только `r', поэтому эта попытка неудачна. Следующий вариант -- это поставить в соответствие с `а*' только две буквы `а'. При таком выборе остаток регулярного выражения успешно соответствует строке.
+
это такой же постфиксный оператор, как и `*', за исключением того, что он требует, чтобы предшествующее ему выражение сопоставлялось по крайней мере один раз. Так например, `ca+r' будет соответствовать строкам `car' и `caaar', но не строке `cr', тогда как `ca*r' соответствует всем трем строкам.
?
постфиксный оператор, как и `*', но он может соответствовать предшествующему выражению либо один раз, либо ни одного. Например, `ca?r' будет соответствовать `car' или `cr' и ничему больше.
[ ... ]
это набор знаков, который начинается `[' и завершается `]'. В простейшем случае совпадающий набор формируют знаки между этими скобками. Таким образом, `[ad]' соответствует либо одной `a', либо одному `d', а `[ad]*' соответствует любой строке, составленной просто из `а' и `d' (включая пустую строку), из всего этого следует, что `c[ad]*r' соответствует `cr', `car', `cdr', `caddaar' и так далее. Вы также можете включить в множество знаков интервалы, написав два знака, разделенные `-'; таким образом, `[a-z]' соответствует любой строчной букве ASCII. Интервалы могут быть свободно перемешаны с отдельными знаками, как в `[a-z$%.]', что соответствует любой строчной букве ASCII, или `$', или `%' или точке. Заметим, что специальные знаки регулярных выражений внутри такого множества больше не являются специальными. Внутри знакового множества существуют совершенно другой набор специальных знаков: `]', `-' и `^'. Чтобы включить в знаковый набор `]', вы должны поставить его первым. Например, `[]а]' соответствует `]' или `а'. Чтобы включить `-', напишите `-' первым или последним знаком в наборе или поместите его после указания интервала. Таким образом, `[]-]' соответствует `]' и `-'. Чтобы включить в набор знак `^', пишите его где угодно, но не первым. Если вы задаете интервал при поиске без учета регистра, вы должны либо написать оба конца интервала заглавными буквами, либо оба строчными, либо оба они не должны быть буквами. Поведение интервала с концами, заданными в разных регистрах, определено плохо и может быть изменено в будущих версиях Emacs.
[^ ... ]
`[^' начинает дополнительный набор знаков, который соответствует любому знаку, исключая описанные в нем. Таким образом, `[^a-z0-9A-Z]' соответствует всем знакам, исключая буквы и цифры. `^' не является специальным в наборе знаков, если он не стоит первым. Знак, следующий за `^', трактуется так, как если бы он был первым (иными словами, `-' и `]' здесь не являются специальными). Дополнительный набор знаков может соответствовать знаку новой строки, если он не упоминается как один из несовпадающих знаков. Это противоречит способу обработки регулярных выражений в таких программах, как grep.
^
это специальный знак, который соответствует пустой строке, но только в начале строки сопоставляемого текста. В противном случае, сравнение не удастся. Таким образом, `^foo' соответствует `foo', которая встречена в начале строки.
$
подобен `^', но сравнение происходит только в конце строки. Таким образом, `xx*$' соответствует строке из одного или более `x' в конце строки.
\
имеет две функции: отменяет особый смысл специальных знаков (включая `\') и вводит дополнительные специальные конструкции. Так как `\' отменяет особый смысл специальных знаков, то `\$' -- это регулярное выражение, которое соответствует только `$', а `\[' -- регулярное выражение, которое соответствует только `[', и так далее.

Замечание: для исторической совместимости специальные знаки трактуются как обычные знаки, если они находятся в контексте, в котором их специальный смысл не имеет значения. Например, `*foo' трактует `*' как обыкновенный, так как не существует предыдущего выражения, на которое может подействовать `*'. Плохо быть зависимым от этого правила; лучше всегда явно отменять особый смысл специальных знаков независимо того, где они находятся.

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

\|
описывает альтернативу. Два регулярных выражения a и b с `\|' между ними формируют выражение, которое соответствует любому из них в отдельности: либо a, либо b. Это работает так: сначала пробуется a, и если соответствие не найдено, пробуется b. Таким образом, `foo\|bar' соответствует либо `foo', либо `bar', но не другой строке. `\|' применяется к самым большим охватывающим выражениям. Только охватывающие скобки `\( ... \)' могут ограничить группирующую силу `\|'. Существует возможность полного обратного восстановления для обработки многократных использований `\|'.
\( ... \)
группирующая конструкция, которая служит для трех целей:
  1. Чтобы отделить набор альтернатив `\|' от других операций. Таким образом, `\(foo\|mar\)x' соответствует либо `foox', либо `marx'.
  2. Чтобы ограничить сложное выражение для действия постфиксных операторов `*', `+' и `?'. Таким образом, `ba\(na\)*' соответствует `bananana' и так далее с любым (нулевым или большим) числом строк `na'.
  3. Чтобы отметить соответствующую подстроку для будущей ссылки.
Это последнее применение не является следствием идеи ограничения группы; это отдельное свойство, которое определено как второе значение той же самой конструкции `\( ... \)'. На практике между этими двумя значениями не оказывается противоречий.
\n
соответствует тексту, совпавшему с n-ным появлением конструкции `\( ... \)'. После конца конструкции `\( ... \)' сопоставление запоминает начало и конец текста, совпавшего с этой конструкцией. Затем, позднее в регулярном выражении, вы можете использовать `\', за которым следует цифра n, чтобы сказать: "сопоставить с том же текстом, который совпал с n-ным появлением конструкции `\( ... \)'". Строкам, соответствующим первым девяти конструкциями `\( ... \)', появляющимся в регулярном выражении, присваиваются номера от 1 до 9 в том порядке, в каком в регулярном выражении появились открывающие скобки. Конструкции от `\1' до `\9' могут использоваться для ссылки на текст конструкции `\( ... \)' с этим номером. Например, `\(.*\)\1' соответствует любой строке, не содержащей знаков перевода строки, которая состоит из двух одинаковых половин. `\(.*\)' соответствует первой половине, которая может быть любой, но `\1', что идет следом, должна соответствовать точно такому же тексту. Если для какой-нибудь конструкции `\( ... \)' найдено более одного соответствия (что может легко произойти, если за ней следует `*'), то запоминается только последнее совпадение.
\`
соответствует пустой строке, но только в начале буфера или строки, где происходит поиск.
\'
соответствует пустой строке, но только в конце буфера или строки, где происходит поиск.
\=
соответствует пустой строке, но только в точке.
\b
соответствует пустой строке, если эта конструкция находится в начале или конце слова. Таким образом, `\bfoo\b' соответствует любому появлению `foo' как отдельного слова. `bballs?\b' соответствует `ball' или `balls' как отдельным словам. `\b' находит соответствие в начале или конце буфера, независимо от того, какой текст идет далее.
\B
соответствует пустой строке, если только она находится не в начале или конце слова.
\<
соответствует пустой строке, если она находится в начале слова. `\<' находит соответствие в начале буфера, но только если затем идет знак, являющийся частью слова.
\>
соответствует пустой строке, если она находится в конце слова. `\>' находит соответствие в конце буфера, но только если буфер завершается знаком, являющимся частью слова.
\w
соответствует любому знаку, являющемуся частью слова. Какие именно это знаки, определяет синтаксическая таблица. Смотрите раздел Синтаксическая таблица.
\W
соответствует любому знаку, не являющемуся частью слова.
\sc
соответствует любому знаку, чей синтаксис определяется кодом c. Здесь c -- это знак, который представляет собой синтаксический код, например, это `w' для части слова, `-' для пробельных знаков, `(' для открывающей скобки, и так далее. Вы можете обозначить пробельный знак (который может быть переводом строки) либо как `-', либо одним пробелом.
\Sc
соответствует любому знаку, чей синтаксис не определяется кодом c.

Конструкции, имеющие отношение к словам и синтаксису, управляются установками в синтаксической таблице (смотрите раздел Синтаксическая таблица).

Далее представлено сложное регулярное выражение, используемое Emacs для распознавания конца предложения вместе с любыми пробельными знаками, которые идут следом. Оно дано в синтаксисе Лиспа, чтобы дать вам возможность отличить пробелы от знаков табуляции. В синтаксисе Лиспа, константная строка начинается и заканчивается двойными кавычками. `\"' обозначает двойные кавычки как часть регулярного выражения, `\\' обозначает обратную косую черту, `\t' обозначает знак табуляции, а `\n' -- знак новой строки.

"[.?!][]\"')]*\\($\\|\t\\|  \\)[ \t\n]*"

Здесь последовательно содержатся четыре части: набор знаков, соответствующий точке, `?' или `!'; набор знаков, соответствующий парным квадратным скобкам, кавычкам или круглым скобкам, повторяемым любое число раз; альтернатива, заключенная в скобки с обратными косыми чертами, которая соответствует концу строки, табуляции или двум пробелам; и набор знаков, соответствующий любым пробельным знакам, повторяющимся любое число раз.

Чтобы ввести это регулярное выражение интерактивно, вы напечатали бы TAB, чтобы получить знак табуляции, и C-j, чтобы получить знак перевода строки. Вы также печатали бы одиночные обратные косые черты как есть, а не дублировали бы их в соответствии с синтаксисом Лиспа.

Поиск и регистр букв

Все виды наращиваемого поиска в Emacs обычно игнорируют регистр текста, в котором происходит поиск, если вы задали текст в нижнем регистре. Таким образом, если вы запросили поиск `foo', то совпадениями считаются и `Foo', и `foo' . Регулярные выражения, и в частности наборы знаков, также включаются в это правило: `[aB]' соответствовало бы `a', или `A', или `b' или `B'.

Заглавная буква в любом месте строки наращиваемого поиска делает этот поиск регистрозависимым. Таким образом, поиск `Foo' не найдет `foo' или `FOO'. Это применяется также и к поиску регулярного выражения. Этот эффект исчезает, если вы удалили заглавные буквы из строки поиска.

Если вы установите переменную case-fold-search равной nil, все буквы должны будут совпадать точно, включая регистр. Эта переменная своя для каждого буфера; ее изменение затрагивает только текущий буфер, но существует значение по умолчанию, которое вы тоже можете изменить. Смотрите раздел Локальные переменные. Эта переменная применяется также и к ненаращиваемому поиску, включая те его разновидности, которые осуществляются командами замены (смотрите раздел Команды замены) и командами поиска в истории минибуфера (смотрите раздел История минибуфера).

Команды замены

Глобальные команды поиска и замены не нужны в Emacs так часто, как в других редакторах(2), но они доступны. Кроме простой команды M-x replace-string, которая аналогична такой же команде в большинстве редакторов, существует команда M-x query-replace, которая для каждого появления образца спрашивает вас, надо ли его заменять.

Команды замены обычно работают с текстом от точки до конца буфера; однако, в режиме Transient Mark они действуют на область, когда метка активна. Все команды замены заменяют одну строку (или регулярное выражение) одной строкой замены. Можно выполнить параллельно несколько замен, используя команду expand-region-abbrevs (смотрите раздел Управление расшифровкой сокращения).

Безусловная замена

M-x replace-string RET строка RET новая-строка RET
Заменяет каждое вхождение строки на новую-строку.
M-x replace-regexp RET regexp RET новая-строка RET
Заменяет каждое совпадение с regexp на новую-строку.

Чтобы заменить каждый случай вхождения `foo' после точки на `bar', используется команда M-x replace-string с двумя аргументами `foo' и `bar'. Замещение происходит только в тексте после точки, так, если вы хотите охватить весь буфер, вы должны сначала отправиться в его начало. Все экземпляры вплоть до конца буфера будут заменены; чтобы ограничиться заменой в части буфера, сузьте его до этой части перед выполнением замены (смотрите раздел Сужение). В режиме Transient Mark, если область активна, замена ограничена этой областью (смотрите раздел Режим Transient Mark).

Когда вы выходите из replace-string, точка остается на месте последней замены. Значение точки в момент, когда была запущена команда replace-string, запоминается в списке пометок. C-u C-SPC перемещает вас обратно.

Числовой аргумент ограничивает замену совпадениями, которые окружены ограничителями слов. Значение аргумента роли не играет.

Замена регулярных выражений

Команда M-x replace-string заменяет точные совпадения с одиночной строкой. Аналогичная команда replace-regexp замещает любое совпадение с заданным образцом.

В replace-regexp, новая-строка не обязательно должна быть константой: она может ссылаться на все или часть того, что соответствует регулярному выражению regexp. `\&' в новой-строке означает полный замещаемый текст. `\n', где n -- это цифра, означает то, что было поставлено в соответствие n-ной заключенной в скобки группе в регулярном выражении regexp. Чтобы включить в новый текст знак `\', вы должны ввести `\\'. Например,

M-x replace-regexp RET c[ad]+r RET \&-safe RET

заменит (например) `cadr' на `cadr-safe' и `cddr' на `cddr-safe'.

M-x replace-regexp RET \(c[ad]+r\)-safe RET \1 RET

делает обратное преобразование.

Команды замены и регистр букв

Если первый аргумент в команде замены набран в нижнем регистре, во время поиска вхождений для замены регистр игнорируется -- при условии, что case-fold-search не равна nil. Если case-fold-search установлена в значение nil, регистр учитывается во всех типах поиска.

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

M-x replace-string RET foo RET bar RET

заменяет `foo' в нижнем регистре на `bar' в нижнем регистре, `FOO' в верхнем регистре на `BAR', а `Foo' с первой заглавной буквой на `Bar'. (Три эти альтернативы: все строчные буквы, все заглавные и первая заглавная -- единственные варианты, которые может распознать replace-string.)

Если в строке подстановки использованы буквы верхнего регистра, то они остаются такими при каждой вставке этого текста. Если буквы верхнего регистра используются в первом аргументе, то второй аргумент всегда вставляется в том виде, в котором он дан, без изменения регистра. Аналогично, если переменная case-replace или case-fold-search установлена равной nil, замещение происходит без изменения регистра.

Замена с подтверждением

M-% строка RET новая-строка RET
M-x query-replace RET строка RET новая-строка RET
Заменяет некоторые вхождения строки на новую-строку.
C-M-% regexp RET новая-строка RET
M-x query-replace-regexp RET regexp RET новая-строка RET
Заменяет некоторые совпадения с regexp на новую-строку.

Если вы хотите заменить только некоторые экземпляры `foo' на `bar', но не все, вы не можете использовать обыкновенную replace-string. Вместо этого используется M-% (query-replace). Эта команда находит экземпляры `foo' один за другим, отображает каждый экземпляр и спрашивает вас, надо ли его заменять. Числовой аргумент говорит query-replace, что нужно рассматривать лишь те экземпляры, которые окружены знаками-разделителями слов. Эта команда сохраняет регистр так же, как и replace-string, при условии, что case-replace не равна nil, как это обычно и бывает.

За исключением запроса подтверждения, query-replace работает точно так же, как replace-string, а query-replace-regexp --- как replace-regexp. Эта команда запускается при помощи C-M-%.

Когда вам показывают вхождение строки или совпадение с регулярным выражением regexp, вы можете набрать следующее:

SPC
чтобы заменить это вхождение на новую-строку.
DEL
чтобы перейти к следующему вхождению, не заменяя это.
, (Запятая)
чтобы заменить это вхождение и показать результат. Затем у вас запрашивают ввод еще одного знака, чтобы узнать, что делать дальше. Так как замена уже произведена, то DEL и SPC в этой ситуации эквивалентны; обе переходят к следующему вхождению. Вы можете набрать в этом месте C-r (смотрите ниже), чтобы изменить замененный текст. Вы можете также набрать C-x u, чтобы отменить сделанную замену; эта команда выходит из query-replace, так что если вы хотите делать дальнейшие замены, вы должны использовать C-x ESC ESC RET, чтобы запустить замену заново (смотрите раздел Повтор команд минибуфера).
RET
чтобы выйти без осуществления дальнейших замен.
. (Точка)
чтобы заменить этот экземпляр и затем выйти без продолжения поиска следующих вхождений.
!
чтобы заменить все оставшиеся экземпляры без повторных запросов.
^
чтобы вернуться к положению предыдущего вхождения (или к тому, что им было), если вы изменили его по ошибке. Это делается при помощи выталкивания из списка пометок. Можно использовать только один `^' подряд, так как во время работы query-replace хранится только одна предыдущая позиция замены.
C-r
чтобы войти в новый уровень рекурсивного редактирования, в том случае, когда экземпляр нуждается скорее в редактировании, чем просто в замене его новой-строкой. Когда вы сделаете это, выйдите из этого уровня рекурсивного редактирования, набрав C-M-c, чтобы перейти к следующему вхождению. Смотрите раздел Уровни рекурсивного редактирования.
C-w
чтобы удалить это вхождение и потом войти в новый уровень рекурсивного редактирования, как в C-r. Используйте рекурсивное редактирование для вставки текста и замены удаленного вхождения строки. Когда вы закончите, выйдите из этого уровня рекурсивного редактирования с помощью C-M-c, чтобы перейти к следующему вхождению.
C-l
чтобы восстановить изображение экрана. Потом вы должны набрать еще один знак, чтобы указать, что делать с этим вхождением.
C-h
чтобы просмотреть сообщение, резюмирующее эти варианты. Потом вы должны набрать еще один знак, чтобы указать, что делать с этим вхождением.

Некоторые другие знаки являются синонимами перечисленных выше: y, n и q эквивалентны SPC, DEL и RET.

Кроме этих знаков, любой другой выходит из query-replace и снова считывается как часть последовательности ключей. Таким образом, если вы напечатаете C-k, она выйдет из query-replace и уничтожит текст до конца строки.

Чтобы перезапустить query-replace, когда вы уже из нее вышли, используйте C-x ESC ESC, которая повторит query-replace, так как она использовала минибуфер для чтения аргументов. Смотрите раздел Повторение команды.

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

Другие команды поиска в цикле

Здесь представлены некоторые другие команды, которые находят совпадения с регулярными выражениями. Все они действуют от точки до конца буфера, и все они игнорируют при сопоставлении регистр, если образец не содержит заглавных букв, а case-fold-search отлична от nil.

M-x occur RET regexp RET
Выводит перечень, показывающий каждую строку буфера, которая содержит совпадение с regexp. Числовой аргумент задает число строк контекста, которые должны быть напечатаны перед и после каждой сравниваемой строки; значений по умолчанию -- не печатать контекст. Чтобы ограничить поиск частью буфера, сузьтесь до этой части (смотрите раздел Сужение). Буфер `*Occur*', в который записывается вывод, служит в качестве меню для поиска вхождений в их оригинальном контексте. Щелкните Mouse-2 на вхождении, перечисленном в `*Occur*', или поместите там точку и нажмите RET; это переключит в буфер, где делался поиск, и переместит точку к оригиналу выбранного вхождения.
M-x list-matching-lines
Синоним для M-x occur.
M-x count-matches RET regexp RET
Печатает число совпадений с regexp после точки.
M-x flush-lines RET regexp RET
Удаляет каждую строку, следующую после точки и содержащую совпадение с regexp.
M-x keep-lines RET regexp RET
Удаляет каждую строку, следующую после точки и не содержащую совпадение с regexp.

Кроме того, вы можете использовать из Emacs программу grep для поиска совпадений с регулярным выражением в группе файлов, а затем обратиться к найденным совпадениям последовательно или в произвольном порядке. Смотрите раздел Поиск с Grep под Emacs.

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

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

Наиболее фундаментальная команда для исправления ошибочного редактирования -- это команда отмены, C-x u или C-_. Эта команда отменяет одну команду (как правило), часть команды (в случае query-replace) или несколько самовставляющихся знаков подряд. Последовательное повторение команд C-_ или C-x u отменяет все более ранние изменения до конца доступной информации отмены. Смотрите раздел Отмена сделанных изменений, для получения дальнейших сведений.

Уничтожение ваших ошибок

DEL
Удалить последний знак (delete-backward-char).
M-DEL
Уничтожить последнее слово (backward-kill-word).
C-x DEL
Уничтожить все до начала предложения (backward-kill-sentence).

Символ DEL (delete-backward-char) -- наиболее важная команда исправления. Она удаляет знак перед точкой. Когда ее используют после самовставляющейся знаковой команды, ее можно рассматривать как отмену этой команды. Но избегайте ошибочной мысли, что DEL -- это универсальный способ отменить команду!

Когда ваша ошибка длиннее, чем пара знаков, то может оказаться более удобным использовать M-DEL или C-x DEL. M-DEL уничтожает все знаки назад до начала последнего слова, а C-x DEL уничтожает назад до начала последнего предложения. C-x DEL особенно полезна в случае, когда вы меняете свое мнение о формулировке текста, который вы пишите. M-DEL и C-x DEL записывают уничтоженный текст для восстановления с помощью C-y и M-y. Смотрите раздел Восстановление.

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

Перестановка текста

C-t
Переставить два знака (transpose-chars).
M-t
Переставить два слова (transpose-words).
C-M-t
Переставить два сбалансированных выражения (transpose-sexps).
C-x C-t
Переставить две строки (transpose-lines).

Распространенная ошибка перестановки двух знаков может быть исправлена, если они являются соседними, с помощью команды C-t (transpose-chars). Обычно C-t переставляет два знака, стоящие по обе стороны от точки. Когда она дается в конце строки, то вместо того, чтобы поменять местами последний знак символ и перевод строки, что было бы бесполезно, C-t переставляет последние два знака на строке. Так, если вы отловили вашу ошибку перестановки сразу, вы можете исправить ее просто с помощью C-t. Если вы отловили ее не так быстро, вы должны перевести курсор назад и установить его между двумя переставленными знаками. Если вы переставили пробел и последний знак в слове перед ним, то команды движения по словам служат удобным способом добраться до этого места. Однако, обратный поиск (C-r) часто бывает самым лучшим способом. Смотрите раздел Поиск и замена.

M-t (transpose-words) переставляет слово перед точкой со словом после нее. Она двигает точку вперед через слово, также перемещая вперед слово, предшествующее точке или содержащее ее. Знаки пунктуации между словами не двигаются. Например, `FOO, BAR' превращается в `BAR, FOO', а не в `BAR FOO,'.

C-M-t (transpose-sexps) -- аналогичная команда для перестановки двух выражений (смотрите раздел Списки и s-выражения), а C-x C-t (transpose-lines) меняет местами строки. Они работают так же, как M-t, за исключением определения деления текста на синтаксические единицы.

Числовой аргумент для команд перестановки работает как счетчик повторений: он указывает команде перестановки передвинуть знак (слово, строку, выражение) перед точкой или содержащий ее через несколько других знаков (слов, строк, выражений). Например, C-u 3 C-t передвигает знак перед точкой вперед через три других знака. Это эквивалентно трехкратному повторению C-t. C-u - 4 M-t двигает слово перед точкой назад через четыре слова. C-u - C-M-t отменила бы действие простой C-M-t.

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

Изменение регистра

M-- M-l
Перевести последнее слово в нижний регистр. Отметим, что Meta-- означает Meta-минус.
M-- M-u
Перевести последнее слово в верхний регистр.
M-- M-c
Перевести последнее слово в нижний регистр с первой заглавной буквой.

Набор слова в неправильном регистре -- очень распространенная ошибка. Поэтому команды изменения регистра M-l, M-u и M-c обладают специальным свойством, когда используются с отрицательным аргументом: они не передвигают курсор. Как только вы увидите, что последнее слово набрано неправильно, вы можете просто изменить в нем регистр и продолжать набор. Смотрите раздел Команды преобразования регистра.

Поиск и исправление орфографических ошибок

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

M-x flyspell-mode
Включает режим Flyspell, который выделяет все неправильно написанные слова.
M-$
Проверяет и исправляет написание слова в точке (ispell-word).
M-TAB
Завершает слово перед точкой, основываясь на орфографическом словаре (ispell-complete-word).
M-x ispell-buffer
Проверяет и исправляет написание всех слов в буфере.
M-x ispell-region
Проверяет и исправляет написание всех слов в области.
M-x ispell-message
Проверяет и исправляет написание всех слов в черновике почтового сообщения, за исключением цитируемого материала.
M-x ispell-change-dictionary RET словарь RET
Перезапускает процесс Ispell, используя словарь в качестве словаря.
M-x ispell-kill-ispell
Уничтожает подпроцесс Ispell.

Режим Flyspell предоставляет полностью автоматический способ проверить правописание во время редактирования в Emacs. Он работает путем проверки слов по мере того, как вы изменяете или вставляете их. Когда он находит нераспознанное слово, он выделяет его. Это не влияет на ваше редактирование, но когда вы видите выделенное слово, вы можете переместиться к нему и исправить. Чтобы включить этот режим в текущем буфере, наберите M-x flyspell-mode.

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

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

Для проверки орфографии в слове вокруг точки или после нее и, возможно, для его исправления, используйте команду M-$ (ispell-word). Если слово написано неправильно, эта команда предложит вам несколько вариантов действий.

Чтобы проверить правописание во всем текущем буфере, запустите команду M-x ispell-buffer. Используйте M-x ispell-region для проверки только текущей области. Чтобы проверить орфографию в почтовом сообщении, которое вы пишите, используйте M-x ispell-message; она проверяет весь буфер, но не трогает материал, в котором сделан отступ, или который процитирован из других сообщений.

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

SPC
Пропустить это слово -- продолжать считать это слово неправильным, но не изменять его здесь.
r новое RET
Заменить это слово (только в этом месте) на новое.
R новое RET
Заменить это слово на новое и выполнить query-replace, чтобы вы могли заменить его во всех других местах буфера, если хотите.
цифра
Заменить это слово (только в этом месте) на одно из показанных похожих слов. Каждое похожее слово перечисляется с цифрой; чтобы выбрать его, наберите эту цифру.
a
Принять неправильное слово -- считать его правильным, но только в этом сеансе редактирования.
A
Принять неправильное слово -- считать его правильным, но только в этом сеансе редактирования и для этого буфера.
i
Вставить это слово в ваш личный файл словаря, чтобы Ispell отныне считал его правильным даже в будущих сеансах.
u
Вставить это слово в нижнем регистре в ваш личный файл словаря.
m
Как i, но вы также можете указать сведения о завершении для словаря.
l слово RET
Поискать в словаре слова, сопоставляющиеся со словом. Эти слова становятся новым списком "похожих слов"; вы можете выбрать для замены одно из них, набрав цифру. Вы можете использовать в слове знак `*' для описания шаблона.
C-g
Выйти из интерактивной проверки правописания. Вы можете перезапустить ее позже с помощью C-u M-$.
X
То же, что и C-g.
x
Выйти из интерактивной проверки правописания и переместить точку назад, где она была, когда вы запустили проверку.
q
Выйти из интерактивной проверки правописания и уничтожить процесс Ispell.
C-l
Перерисовать экран.
C-z
Этот ключ имеет свое обычное значение (приостановить Emacs или минимизировать этот фрейм).

Команда ispell-complete-word, которая привязана к ключу M-TAB в режиме Text и родственных с ним режимах, показывает список завершений, основываясь на исправлении орфографии. Вставьте начало слова, а затем напечатайте M-TAB; эта команда отобразит окно со списком завершений. Чтобы выбрать одно из перечисленных завершений, щелкните на нем Mouse-2 или переместите к нему курсор и нажмите RET. Смотрите раздел Режим Text.

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

Ispell использует два словаря: стандартный и ваш личный. Переменная ispell-dictionary задает имя используемого файла стандартного словаря. Значение nil говорит, что нужно использовать словарь по умолчанию. Команда M-x ispell-change-dictionary устанавливает эту переменную и затем перезапускает подпроцесс Ispell, чтобы он использовал другой словарь.

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

Операционная система хранит постоянные даные в именованных файлах. Поэтому большая часть текста, который вы редактируете в 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'.

По вашему выбору 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 как привилегированный пользователь.

Когда файл находится под управлением системы контроля версий (смотрите раздел Управление версиями), 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  

        * 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  

        * 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  

        * 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  

        * 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'.


Обсудить данную тему на нашем форуме "Все о Linux"