Go to the first, previous, next, last section, table of contents.


Редактирование программ

В Emacs есть много команд, предназначенных для понимания синтаксиса языков программирования, таких как Лисп и Си. Эти команды могут:

Команды для слов, предложений и абзацев очень удобны при редактировании программ, даже хотя их традиционным применением является редактирование текстов на естественном языке. Большинство символов содержат слова (see section Слова); предложения могут быть найдены в строках или комментариях (see section Предложения). Абзацы так таковые не присутствуют в коде, но команды работы с абзацами тем не менее полезны, так как основные режимы для языков программирования определяют абзацы как куски текста, начинающиеся и заканчивающиеся пустыми строками (see section Абзацы). Разумное использование пустых строк для улучшения читаемости программы будет также предоставлять командам, оперрирующим с абзацами, интересные куски текста для работы.

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

Основные режимы для языков программирования

Emacs также имеет основные режимы для языков программирования Лисп, Scheme (вариант Лиспа), Awk, Си, Си++, Фортран, Icon, Java, Objective-C, Паскаль, Perl, Pike, CORBA IDL, и Tcl. Есть также основной режим для Make-файлов, называемый режимом Makefile. Второй альтернативный режим для Perl называется режимом CPerl.

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

Есть несколько разновидностей режима Lisp, которые отличаются способом взаимодействия с исполнением Лиспа. See section Вычисление выражений Emacs-Lisp.

Каждый из основных режимов для языка программирования определяет ключ TAB для запуска функции, делающей отступ, которой известны соглашения об отступах для этого языка и которая соответственно изменяет отступ текущей строки. Например, в режиме С, TAB привязан к c-indent-line. C-j обычно определяется так, чтобы делать RET, за которым следует TAB; таким образом, эта команда тоже делает отступ в режимозависимом виде.

В большинстве языков программирования отступ часто изменяется от строки к строке. Следовательно, основные режимы для таких языков перепривязывают DEL так, чтобы он трактовал знак табуляции как эквивалентное количество пробелов (используя команду backward-delete-char-untabify). Это позволяет стирать отступ по одному столбцу, не заботясь о том, сделан ли он с помощью пробелов или знаков табуляции. Чтобы удалить в этих режимах знак табуляции перед точкой, используйте C-b C-d.

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

Включение основного режима запускает обычную ловушку, называемую ловушкой режима, которая является значением лисповской переменной. Для каждого основного режима есть своя ловушка, и имя этой ловушки всегда составляется из имени команды, запускающей этот режим, и слова `-hook'. Например, включение режима С запускает ловушку c-mode-hook, тогда как включение режима Lisp запускает ловушку lisp-mode-hook. See section Ловушки.

Списки и s-выражения

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

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

Другие команды имеют дело с выражениями или s-выражениями. Слово `s-выражение' происходит от s-expression, старого термина для выражения в Лиспе. Но в Emacs понятие `s-выражение' не ограничивается Лиспом. Оно обозначает выражение в любом языке, на котором написана ваша программа. Каждый язык программирования имеет свой собственный основной режим, который настраивает синтаксические таблицы так, что выражения на этом языке рассматриваются как s-выражения.

Обычно s-выражение включает в себя символы, числа и строковые константы, а также все, что содержится в круглых, квадратных или фигурных скобках.

В языках, которые используют префиксные и инфиксные операторы, таких как Си, не все выражения могут быть s-выражениями. Например, режим С не распознает `foo + bar' как s-выражение, несмотря на то, что это является выражением Си; он распознает `foo' как одно s-выражение и `bar' как другое, со знаком `+' в качестве пунктуации между ними. Это фундаментальная неоднозначность: как `foo + bar', так и `foo' являются законными кандидатами на s-выражение, через которое нужно передвинуться, если точка находится на `f'. Заметьте, что `(foo + bar)' -- это единое s-выражение в режиме С.

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

Команды работы со списками и s-выражениями

C-M-f
Передвинуться вперед через s-выражение (forward-sexp).
C-M-b
Передвинуться назад через s-выражение (backward-sexp).
C-M-k
Уничтожить s-выражение вперед (kill-sexp).
C-M-DEL
Уничтожить s-выражение назад (backward-kill-sexp).
C-M-u
Перейти вверх и назад по структуре списка (backward-up-list).
C-M-d
Перейти вниз и вперед по структуре списка (down-list).
C-M-n
Передвинуться вперед через список (forward-list).
C-M-p
Передвинуться назад через список (backward-list).
C-M-t
Переставить выражения (transpose-sexps).
C-M-@
Поставить метку после следующего выражения (mark-sexp).

Чтобы передвинуться вперед через s-выражение, используйте C-M-f (forward-sexp). Если первая значащая литера после точки -- это открывающий ограничитель (`(' в Лиспе; `(', `[' или `{' в Си), то C-M-f передвигает за парный закрывающий ограничитель. Если этот знак начинает символ, строку или число, то C-M-f передвигает через них.

Команда C-M-b (backward-sexp) двигает назад через s-выражение. Подробные правила похожи на описанные выше для C-M-f, но с противоположным направлением. Если перед s-выражением стоят какие-либо префиксные символы (в Лиспе это одиночная кавычка, обратная кавычка и запятая), то C-M-b переходит и через них. Команды для s-выражений передвигаются через комментарии, как это делается для пропусков в большинстве режимов.

C-M-f или C-M-b с аргументом повторяют операцию заданное число раз; с отрицательным аргументом, они перемещают в противоположном направлении.

Уничтожение целого s-выражения может быть сделано при помощи C-M-k (kill-sexp) или C-M-DEL (backward-kill-sexp). C-M-k уничтожает знаки, через которые передвинула бы C-M-f, а C-M-DEL уничтожает знаки, через которые передвинула бы C-M-b.

Команды для списков передвигают через списки, как и команды s-выражений, но легко перескакивают через любое количество других видов s-выражений (символы, строки и так далее). Это C-M-n (forward-list) и C-M-p (backward-list). Они полезны в основном тем, что обычно игнорируют комментарии (так как комментарии как правило не содержат никаких списков).

C-M-n и C-M-p остаются на одном уровне скобок, когда это возможно. Чтобы передвинуться вверх на один (или n) уровень, используйте C-M-u (backward-up-list). C-M-u двигает назад и вверх мимо одного непарного открывающего ограничителя. Положительный аргумент служит счетчиком повторов; отрицательный аргумент меняет направление движения и также запрашивает повторение, таким образом, в этом случае движение происходит вперед и вверх на один или больше уровней.

Чтобы передвинуться вниз по структуре списков, используйте C-M-d (down-list). В режиме Lisp, где `(' -- это единственный открывающий ограничитель, это почти то же самое, что и поиск `('. Количество уровней скобок, на какое следует спуститься, определяет аргумент.

Команда C-M-t (transpose-sexp), которая переносит предыдущее s-выражение через следующее, отчасти кажется случайно сюда попавшей, но тем не менее она очень удобна. Аргумент служит для подсчета числа повторов, а отрицательный аргумент перетаскивает выражение в обратном направлении (таким образом отменяя действие C-M-t с положительным аргументом). Аргумент, равный нулю, вместо того чтобы ничего не делать, переставляет местами s-выражения, кончающиеся после точки и метки.

Чтобы установить область вокруг следующего s-выражения в буфере, используйте C-M-@ (mark-sexp), которая ставит пометку в то же самое место, куда должна бы была передвинуться C-M-f. C-M-@ воспринимает аргумент так же, как C-M-f. В частности, отрицательный аргумент удобен для установки метки в начале предыдущего s-выражения.

Понимание синтаксиса командами для списков и s-выражений полностью управляется синтаксической таблицей. Любой знак может быть объявлен, например, открывающим ограничителем и действовать как открывающая круглая скобка. See section Синтаксическая таблица.

Определения функций

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

C-M-a
Передвинуться к началу текущего или предшествующего определения функции (beginning-of-defun).
C-M-e
Передвинуться в конец текущего или следующего определения функции (end-of-defun).
C-M-h
Пометить область вокруг всего текущего или следующего определения функции (mark-defun).

Команды движения к началу или концу текущего определения функции --- это C-M-a (beginning-of-defun) и C-M-e (end-of-defun).

Если вы пожелаете произвести какие-то действия над текущим определением функции, используйте C-M-h (mark-defun), которая ставит точку в начале и метку в конце текущего или следующего определения функции. Например, это простейший способ получить готовое для перемещения в другое место определение функции. В режиме С, C-M-h запускает функцию c-mark-function, которая почти эквивалентна mark-defun; различие состоит в том, что она переходит через объявления аргументов, имя функции и тип возвращаемых данных, так что функция Си оказывается внутри области полностью. See section Команды для пометки текстуальных объектов.

Emacs предполагает, что любые открывающие скобки, найденные в самом левом столбце, -- это начало определения функции. Поэтому никогда не ставьте открывающие скобки с левого края в Лисп-файле, если они не являются началом списка верхнего уровня. Никогда не ставьте открывающую фигурную скобку или другой открывающий ограничитель в начале строки в программе на Си, если только они не начинают тело функции. Большинство возможных проблем возникает, когда вы хотите поставить открывающий ограничитель в начале строки внутри строковой константы. Чтобы избежать неприятностей, поставьте экранирующий знак (`\' в Си и Emacs Lisp, `/' в некоторых других диалектах Лиспа) перед открывающим ограничителем. Это не повлияет на содержимое строки.

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

Отступы в программах

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

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

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

TAB
Установить отступ текущей строки.
C-j
Эквивалент RET, за которым следует TAB (newline-and-indent).

Основная команда отступа -- это TAB, которая дает текущей строке правильный отступ, основываясь на отступе предыдущих строк. Функция, которую запускает TAB, зависит от основного режима; в режиме Lisp это lisp-indent-line, в режиме С это c-indent-line и так далее. Эти функции понимают различные синтаксисы разных языков, но все они делают примерно одно и то же. TAB в основном режиме любого языка программирования вставляет или удаляет пробельные знаки в начале текущей строки, независимо от того, где в строке располагается точка. Если точка находится среди пробельных знаков в начале строки, TAB оставляет ее после них; в противном случае TAB оставляет точку фиксированной по отношению к окружающим ее знакам.

Чтобы вставить в точке знак табуляции, используйте C-q TAB.

При вводе нового кода используйте C-j (newline-and-indent), которая эквивалентна RET, за которой следует TAB. C-j создает пустую строку, а затем дает ей соответствующий отступ.

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

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

Отступ в нескольких строках

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

C-M-q
Сделать новый отступ во всех строках в пределах одного списка (indent-sexp).
C-u TAB
Сдвинуть весь список жестко в сторону так, чтобы его первая строка получила надлежащий отступ.
C-M-\
Сделать новый отступ во всех строках в области (indent-region).

Вы можете вновь сделать отступ содержимого одиночного списка, переместив точку в его начало и набрав C-M-q (это команда indent-sexp в режиме Lisp, c-indent-exp в режиме С; она также привязана к другим подходящим функциям в других режимах). Отступ строки, на которой начинается это s-выражение, не изменяется; поэтому изменяется только относительный отступ в пределах списка, а не его позиция. Чтобы исправить также и его позицию, наберите TAB перед C-M-q.

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

Можно указать диапазон строк, в которых следует вновь сделать отступ, другим способом -- с помощью области. Команда C-M-\ (indent-region) применяет TAB к каждой строке, чей первый знак находится между точкой и меткой.

Настройка отступов для Лиспа

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

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

Если переменная lisp-indent-offset не равна nil, то она перекрывает обычный шаблон отступа для второй строки выражения, так что такие строки всегда сдвигаются вправо на lisp-indent-offset столбцов дальше, чем содержащий их список.

Стандартный шаблон перекрывается в некоторых определенных функциях. Для функций, чьи имена начинаются с def, отступ второй строки всегда делается на lisp-body-indention дополнительных столбцов дальше открывающей скобки, начинающей выражение.

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

nil
Это то же самое, что и отсутствие свойства; используется стандартный шаблон отступа.
defun
Шаблон, используемый для имен функций, которые начинаются с def, также используется и для этой функции.
число, n
Первые n аргументов этой функции считаются отличительными аргументами, остальные рассматриваются как тело выражения. Строка в этом выражении отступается в соответствии с тем, является ли в ней первый аргумент отличительным или нет. Если аргумент является частью тела, то строка отступается на lisp-body-indent столбцов больше, чем открывающая скобка, начинающая содержащее ее выражение. Если аргумент является отличительным, и это первый или второй аргумент, то отступ делается на вдвое большее число дополнительных столбцов. Если аргумент отличителен и не является первым или вторым, то для этой строки применяется стандартный шаблон.
символ, символ
символ должен быть именем функции; эта функция вызывается для вычисления отступа строки в пределах этого выражения. Функция получает два аргумента:
состояние
Значение, возвращаемое из parse-partial-sexp (это примитив Лиспа для подсчета величины отступов и вложенностей), когда она делает разбор вплоть до начала этой строки.
позиция
Позиция, с которой начинается строка, в которой делается отступ.
Она должна возвращать либо число, которое равно количеству столбцов отступа для этой строки, либо список, чей головной элемент является таким числом. Отличие между возвращением числа и возвращением списка заключается в том, что число говорит, что все следующие строки того же уровня вложенности должны получать такой же отступ, как эта строка; список говорит, что следующие строки могут требовать отличные отступы. Это важно, если отступы подсчитываются с помощью C-M-q; если значение -- это число, то C-M-q не нуждается в пересчете отступа для следующих строк до конца списка.

Команды для отступов в Си

Вот команды для создания отступов в режиме C и родственных с ним:

C-c C-q
Обновляет отступ в текущем определении функции верхнего уровня или собирает в одно целое объявление типа (c-indent-defun).
C-M-q
Обновляет отступ в каждой строке сбалансированного выражения, которое следует после точки (c-indent-exp). Префиксный аргумент подавляет проверку ошибок и вывод предупреждений о недопустимом синтаксисе.
TAB
Обновляет отступ в текущей строке и/или в некоторых случаях вставляет знак табуляции (c-indent-command). Если c-tab-always-indent равна t, эта команда всегда обновляет отступ текущей строки и не делает ничего больше. Это принимается по умолчанию. Если эта переменная равна nil, данная команда обновляет отступ текущей строки, только если точка находится с левого края или на отступе; в противном случае она вставляет табуляцию (или эквивалентное число пробелов, если indent-tabs-mode равна nil). Любое другое значение (не nil или t) означает, что нужно всегда обновлять отступ строки, а также вставлять знак табуляции, если точка находится внутри комментария, строки или директивы препроцессора.
C-u TAB
Обновляет отступ текущей строки в соответствии с ее синтаксисом; кроме того, жестко смещает все остальные строки выражения, начинающегося на текущей строке. See section Отступ в нескольких строках.

Чтобы обновить отступ всего текущего буфера, наберите C-x h C-M-\. Это сначала выделяет весь буфер как область, а затем обновляет отступ в этой области.

Чтобы обновить отступ в текущем блоке, используйте C-M-u C-M-q. Эта команда перемещает к началу блока и делает в нем отступ.

Настройка отступа в Си

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

Шаг 1 -- синтаксический анализ

На первом шаге механизм отступов в Си смотрит на строку перед той, в которой вы в данный момент делаете отступ, и определяет синтаксические компоненты конструкции на этой строке. Он строит список этих синтаксических компонентов, где каждый компонент содержит синтаксический символ и, иногда, позицию в буфере. Некоторые синтаксические символы описывают грамматические элементы, например statement и substatement; другие описывают положения в составе грамматических элементов, например class-open и knr-argdecl.

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

Вот пример. Предположим, что у нас есть следующий код в буфере с режимом C++ (номера строк в действительности не появляются в буфере):

1: void swap (int& a, int& b)
2: {
3:   int tmp = a;
4:   a = b;
5:   b = tmp;
6: }

Если вы наберете C-c C-s (что запускает команду c-show-syntactic-information) на строке 4, будет показан результат работы механизма отступов для этой строки:

((statement . 32))

Это указывает на то, что данная строка является оператором, и она имеет отступ относительно позиции 32 в буфере, то есть относительно `i' в int на строке 3. Если вы переместите курсор к строке 3 и наберете C-c C-s, это покажет следующее:

((defun-block-intro . 28))

Это указывает на то, что строка int -- это первый оператор в блоке, и она имеет отступ относительно позиции 28, то есть фигурной скобки сразу после заголовка функции.

Вот еще один пример:

1: int add (int val, int incr, int doit)
2: {
3:   if (doit)
4:     {
5:       return (val + incr);
6:     }
7:   return (val);
8: }

Если в строке 4 набрать C-c C-s, вы увидите вот что:

((substatement-open . 43))

Это говорит, что данная фигурная скобка открывает блок подоператора. Кстати, подоператор -- это строка после операторов if, else, while, do, switch, for, try, catch, finally или synchronized.

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

Шаг 2 -- подсчет отступа

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

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

Следующие примеры демонстрируют работу механизма отступов в языке Си:

1: void swap (int& a, int& b)
2: {
3:   int tmp = a;
4:   a = b;
5:   b = tmp;
6: }

Предположим, что точка находится на строке 3, и вы нажимаете TAB, чтобы обновить в этой строке отступ. Как объяснялось выше (see section Шаг 1 -- синтаксический анализ), синтаксическим компонетом этой строки будет:

((defun-block-intro . 28))

В данном случае при подсчете отступа сначала просматривается defun-block-intro в ассоциативном списке c-offsets-alist. Предположим, что там найдено число 2; оно добавляется к общему (инициализированному нулем), выдавая общей обновленный отступ в 2 пробела.

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

1: int add (int val, int incr, int doit)
2: {
3:   if (doit)
4:     {
5:       return(val + incr);
6:     }
7:   return(val);
8: }

Если вы нажмете TAB в строке 4, повторяется такой же процесс, но с иными данными. Список синтаксических компонентов для этой строки таков:

((substatement-open . 43))

Здесь первое, что делается для посчета отступа, -- ищется символ substatement-open в c-offsets-alist. Будем считать, что сдвиг для этого символа равен 2. В этом месте промежуточное общее значение равно 2 (0 + 2 = 2). Затем к нему добавляется номер строки позиции 43 в буфере, где стоит `i' из if на строке 3. Этот знак расположен во втором столбце на строке. Итого в сумме получается 4 пробела.

Если при анализе строки появляется синтаксический символ, который отсутствует в c-offsets-alist, он игнорируется; и это является ошибкой, если кроме того переменная c-strict-syntax-p отлична от nil.

Изменение стиля отступов

Есть два способа настроить стиль отступов для режимов, подобных режиму C. Во-первых, вы можете выбрать один из предопределенных стилей, каждый из которых задает сдвиги для всех синтаксических символов. Для большей гибкости вы можете настоить обработку отдельных синтаксических символов. See section Синтаксические символы, перечень всех определенных синтаксических символов.

M-x c-set-style RET стиль RET
Выбирает предопределенный стиль стиль. Чтобы получить перечень поддерживаемых стилей, наберите при вводе стиля знак ?; чтобы узнать, как выглядит тот или иной стиль, выберите его и примените для фрагмента кода на Си.
C-c C-o символ RET сдвиг RET
Устанавливает сдвиг для синтаксического символа символ (c-set-offset). Второй аргумент, сдвиг, указывает новую величину сдвига.

Размер отступа для каждого синтаксического символа управляется переменной c-offsets-alist. Ее значение -- это ассоциативный список, и каждый элемент этого списка имеет форму (синтаксический-символ . сдвиг). Изменяя сдвиги для разных синтаксических символов, вы можете настраивать отступы в мельчайших подробностях. Чтобы изменить этот ассоциативный список, используйте c-set-offset (смотрите ниже).

Значение каждого сдвига в c-offsets-alist может быть целым числом, именем функции или переменной, списком или одним их символов +, -, ++, --, * или /, обозначающих положительные или отрицательные кратные переменной c-basic-offset. Таким образом, если вы хотите поменять уровни отступов с трех пробелов на два пробела, установите c-basic-offset в значение 3.

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

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

Команда C-c C-o (c-set-offset) -- это простейший способ установить сдвиги, как интерактивно, так и в вашем файле `~/.emacs'. Сначала укажите синтаксический символ, а потом желаемый сдвиг. See section Синтаксические символы, перечень допустимых синтаксических символов и их значений.

Синтаксические символы

Это таблица допустимых синтаксических символов для отступов режима C и родственных с ним режимов и их синтаксические значения. Обычно всем этим символам приписывается сдвиг в c-offsets-alist.

string
Внутри строки, занимащей несколько строк в буфере.
c
Внутри многострочного блочного комментария в стиле Си.
defun-open
На фигурной скобке, которая открывает определение функции.
defun-close
На фигурной скобке, которая закрывает определение функции.
defun-block-intro
На первой строке определения функции верхнего уровня.
class-open
На фигурной скобке, которая открывает определение класса.
class-close
На фигурной скобке, которая закрывает определение класса.
inline-open
На фигурной скобке, которая открывает определяемый внутри класса inline-метод.
inline-close
На фигурной скобке, которая закрывает определяемый внутри класса inline-метод.
extern-lang-open
На фигурной скобке, которая открывает блок на внешнем языке.
extern-lang-close
На фигурной скобке, которая закрывает блок на внешнем языке.
func-decl-cont
На области между списком аргументов в определении функции и открывающей это определение фигурной скобкой (исключая определения функций в стиле K&R). В Си вы не можете писать здесь ничего, кроме пробельных знаков и комментариев; в Си++ и Java в этом контекте могут появляться объявления throws и другие вещи.
knr-argdecl-intro
На первой строке объявления аргументов в стиле K&R Си.
knr-argdecl
На одной из последующих строк объявления аргументов в стиле K&R Си.
topmost-intro
На первой строке определения конструкции самого верхнего уровня.
topmost-intro-cont
На остальных строках определения самого верхнего уровня.
member-init-intro
На первой строке списка инициализаций членов.
member-init-cont
На последующих строках списка инициализаций членов.
inher-intro
На первой строке списка множественного наследования.
inher-cont
На одной их последующих строк множественного наследования.
block-open
На открывающей фигурной скобке операторного блока.
block-close
На закрывающей фигурной скобке операторного блока.
brace-list-open
На открывающей фигурной скобке списка массива enum или static.
brace-list-close
На закрывающей фигурной скобке списка массива enum или static.
brace-list-intro
На первой строке списка массива enum или static.
brace-list-entry
На одной их последующих строк списка массива enum или static.
brace-entry-open
На одной из последующих строк списка массива enum или static, когда строка начинается с открывающей фигурной скобки.
statement
На обычном операторе.
statement-cont
На строке продолжения оператора.
statement-block-intro
На первой строке нового операторного блока.
statement-case-intro
На первой строке "блока" case.
statement-case-open
На первой строке блока case, начинающейся с фигурной скобки.
inexpr-statement
На операторном блоке внутри выражения. Это используется для расширения GNU в языке Си и для для специальных функций Pike, которые принимают в качестве аргумента операторный блок.
inexpr-class
На определении класса внутри выражения. Это используется для аноноимных классов и аноноимных инициализаторов массивов в Java.
substatement
На первой строке после if, while, for, do или else.
substatement-open
На фигурной скобке, открывающей блок подоператора.
case-label
На метке case или default.
access-label
На метках доступа Си++ private, protected или public.
label
На обычной метке.
do-while-closure
На while, который завершает конструкцию do-while.
else-clause
На else конструкции if-else.
catch-clause
На строках catch и finally в конструкциях try...catch в Си++ и Java.
comment-intro
На строке, содержащей только начало комментария.
arglist-intro
На первой строке списка аргументов.
arglist-cont
На одной из последующих строк списка аргументов, когда на строке с открывающей список аргументов круглой скобкой нет ни одного аргумента.
arglist-cont-nonempty
На одной из последующих строк списка аргументов, когда на строке с открывающей список аргументов круглой скобкой есть хотя бы один аргумент.
arglist-close
На закрывающей круглой скобке списка аргументов.
stream-op
На одной строк продолжения конструкции потокового оператора.
inclass
На конструкции, вложенной в определение класса. Отступ относителен открывающей фигурной скобке определения класса.
inextern-lang
На конструкции, вложенной в блок на внешнем языке.
inexpr-statement
На первой строке операторного блока внутри выражения. Это нужно для расширения GCC в языке Си, которое использует синтаксис ({ ... }). Это также нужно для специальных функций в Pike, принимающих в качестве аргумента операторный блок.
inexpr-class
На первой строке определения класса внутри выражения. Это используется для аноноимных классов и аноноимных инициализаторов массивов в Java.
cpp-macro
На начале макроса препроцессора.
friend
На объявлении Си++ friend.
objc-method-intro
На первой строке определения метода Objective-C.
objc-method-args-cont
На одной из строк продолжения определения метода Objective-C.
objc-method-call-cont
На одной из строк продолжения вызова метода Objective-C.
inlambda
Как inclass, но применяется внутри лямбда-функций (т.е. анонимных). Используется только в Pike.
lambda-intro-cont
На строке, продолжающей заголовок лямбда-функции, между ключевым словом lambda и телом функции. Используется только в Pike.

Переменные, управляющие отступами в Си

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

c-offsets-alist
Ассоциативный список синтаксических символов и их сдвигов. Вы не должны менять его прямо, делайте это через c-set-offset. See section Изменение стиля отступов, для подробностей.
c-style-alist
Переменная для определения стилей отступов; смотрите ниже.
c-basic-offset
Базовый сдвиг, используемый символами + и - в c-offsets-alist.
c-special-indent-hook
Ловушка для специальных подстроек отступов, определяемых пользователем. Эта ловушка вызывается после того, как в строке уже сделан отступ режимом C или родственным с ним режимом.

Переменная c-style-alist задает предопределенные стили отступов. Каждый элемент имеет форму (имя установка-переменной...), где имя -- это имя стиля. Каждая установка-переменной имеет форму (переменная . значение); переменная -- это одна из настроечных переменных, используемых режимом C, а значение -- это значение для этой переменной, когда используется выбранный стиль.

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

Отступы строк, содержащих только комментарии, также подвержены влиянию переменной c-comment-only-line-offset (see section Комментарии в режимах C).

Стили отступов в Си

Стиль Си -- это набор настроек стиля отступов. Emacs поставляется с несколькими предопределенными стилями отступов для C и родственных режимов, включая gnu, k&r, bsd, stroustrup, linux, python, java, whitesmith, ellemtel и cc-mode. По умолчанию применяется стиль gnu.

Чтобы выбрать нужный вам стиль, используйте команду M-x c-set-style. Задавайте имя стиля в качестве аргумента (регистр не имеет значения). Выбранный стиль применяется только к новым буферам, но не к тем, что вы уже редактируете. Вы также можете установить переменную c-default-style, чтобы указать стиль для различных основных режимов. Ее значением должен быть ассоциативный список, где каждый элемент задает один основной режим и стиль отступов, который для него нужно использовать. Например,

(setq c-default-style
      '((java-mode . "java") (other . "gnu")))

определяет явный выбор для режима Java и велит принимать стиль `gnu' по умолчанию для остальных C-подобных режимов.

Чтобы определить новый стиль отступов в Си, вызовите функцию c-add-style:

(c-add-style имя значения применить-сразу)

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

Если применить-сразу не равна nil, c-add-style переключает в новый стиль сразу после его определения.

Автоматическое отображение парных скобок

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

В Лиспе автоматическое соответствие применяется только к круглым скобкам. В Си оно применяется также к фигурным и квадратным скобкам. Emacs узнает, какие знаки рассматривать как парные ограничители, основываясь на синтаксической таблице, которая устанавливается основным режимом. See section Синтаксическая таблица.

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

Отображением парных скобок управляют три переменные. blink-matching-paren включает или выключает эту возможность; nil выключает, а значение по умолчанию, равное t, включает ее. blink-matching-delay говорит, сколько секунд нужно ожидать; по умолчанию это 1, но на некоторых системах полезно задать часть секунды. blink-matching-paren-distance указывает, сколько знаков в обратном направлении надо исследовать, чтобы найти парный открывающий ограничитель. Если пара не будет найдена на таком расстоянии, то сканирование останавливается и ничего не отображается. Это делается для того, чтобы избежать больших затрат времени на поиск парного ограничителя в том случае, если пары не существует. По умолчанию она равна 12000.

При использовании X Windows вы можете запросить более мощную альтернативную разновидность автоматического показа парных скобок, включив режим Show Paren. Этот режим выключает обычный способ отображения парных скобок и использует вместо него подсветку совпадений. Когда точка находится после закрывающей скобки, подвечиваются эта закрывающая скобка и парная ей открывающая; иначе, если точка находится перед открывающей скобкой, подсвечивается парная скобка. (Подсвечивать открывающую скобку после точки не нужно, потому что поверх этого знака находится курсор.) Для включения и выключения этого режима используйте команду M-x show-paren-mode.

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

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

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

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

M-;
Вставить или выровнять комментарий в текущей строке (indent-for-comment).
C-x ;
Установить столбец комментария (set-comment-column).
C-u - C-x ;
Уничтожить комментарий в текущей строке (kill-comment).
C-M-j
Подобна RET, за которой следует вставка или выравнивание комментария (indent-new-comment-line).
M-x comment-region
Добавить или удалить ограничители комментариев на всех строках области.

Команда, которая создает комментарии, называется M-; (indent-for-comment). Если на строке еще нет комментария, то создается новый комментарий, выровненный по особому столбцу, называемому столбцом комментария. Комментарий создается вставкой строки, с которой, как думает Emacs, должны начинаться комментарии (значение comment-start, смотрите ниже). Точка оставляется за этой строкой. Если текст в строке текста простирается дальше столбца комментария, то делается отступ до подходящей границы (обычно вставляется по крайней мере один пробел). Если основной режим определил строку, завершающую комментарий, то она вставляется после точки, чтобы сохранить правильный синтаксис.

M-; может быть использована также и для выравнивания существующего комментария. Если строка уже содержит начало комментария, то M-; просто передвигает за него точку и делает отступ до принятой позиции. Исключение: комментарии, начинающиеся в столбце 0, не сдвигаются.

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

;; Эта просто пример функции
;;; Здесь годятся и 2, и 3 точки с запятой.
(defun foo (x)
;;; А теперь первая часть функции
  ;; Следующая строка добавляет единицу.
  (1+ x))           ; Эта строка добавляет единицу.

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

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

Команда C-u - C-x ; (kill-comment) уничтожает комментарий в текущей строке, если он там есть. Отступ перед началом комментария также уничтожается. Если на этой строке нет комментария, то ничего не делается. Чтобы перенести комментарий в другую строку, передвиньтесь в конец этой строки, сделайте C-y и затем M-;, чтобы заново его выровнять. Заметьте, что C-u - C-x ; -- это не отдельный ключ; это C-x ; (set-comment-column) с отрицательным аргументом. Эта команда запрограммирована таким образом, что когда она получает отрицательный аргумент, она вызывает kill-comment. Однако, kill-comment -- это допустимая команда, которую вы можете непосредственно привязать к ключу, если вы этого хотите.

Многострочные комментарии

Если вы набираете комментарий и обнаруживаете, что хотели бы продолжить его на другой строке, то вы можете использовать команду C-M-j (indent-new-comment-line). Она завершает набранный вами комментарий, затем создает новую пустую строку и начинает новый комментарий, с отступом под старым комментарием. Когда действует режим Auto Fill, то переход за столбец заполнения во время набора комментария приводит к тому, что комментарий будет продолжаться именно таким образом. Если во время набора C-M-j точка находится не в конце строки, то текст в оставшейся части строки становится частью новой строки комментария.

Чтобы превратить существующие строки в строки комментариев, используйте команду M-x comment-region. Она добавляет ограничители к строкам, которые начинаются в области, делая их таким образом комментариями. С отрицательным аргуменом, она делает обратное --- удаляет ограничители комментариев из строк области.

С положительнм аргументом, comment-region повторяет последний знак из добавляемой последовательности, начинающей комментарий. Таким образом, в режиме Lisp, C-u 2 M-x comment-region добавит `;;' на каждую строку. Повторение ограничителей комментария -- это способ привлечения к нему внимания. В Лиспе для получения правильных отступов вы должны использовать аргумент, равный двум, между определениями функций, и трем -- внутри определений функций.

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

Параметры управления комментариями

Столбец комментария хранится в переменной comment-column. Вы можете явно установить ее на нужное число. Или вы можете использовать команду C-x ; (set-comment-column), которая устанавливает столбец комментария равным тому столбцу, где находится точка. C-u C-x ; устанавливает столбец комментария так, чтобы он соответствовал последнему комментарию перед точкой в этом буфере, и затем делает M-;, чтобы выравнять строку текущего комментария под предыдущую. Отметим, что C-u - C-x ; запускает функцию kill-comment, как описано выше.

Переменная comment-column -- это собственная переменная каждого буфера: установка ее влияет только на текущий буфер, но существует и значение по умолчанию, которое вы также можете изменить с помощью setq-default. See section Локальные переменные. Многие основные режимы инициализируют эту переменную для текущего буфера.

Команды работы с комментариями распознают комментарии, основываясь на регулярном выражении, которое является значением переменной comment-start-skip. Убедитесь, что это регулярное выражение не соответствует пустой строке. Оно может соответствовать чему-то большему, чем просто ограничителю, начинающему комментарий, в самом строгом значении этого слова; например, в режиме С значение этой переменной равно "/\\*+ *", что соответствует дополнительным звездочкам и пробелам после самого `/*'. (Обратите внимание, `\\' требуется в синтаксисе Лиспа для того, чтобы включить в строку `\', которая нужна, чтобы отменить для первой звездочки ее специальное значение в синтаксисе регулярных выражений. See section Синтаксис регулярных выражений.)

Когда команда для комментариев создает новый комментарий, она вставляет в его начало значение comment-start. Значение comment-end вставляется после точки, так что оно будет следовать за текстом, который вы вставите в этот комментарий. В режиме С comment-start имеет значение "/* ", а comment-end имеет значение " */".

Переменная comment-multi-line управляет тем, как ведет себя C-M-j (indent-new-comment-line) при использовании внутри комментария. Если comment-multi-line равна nil, как это обычно и бывает, то комментарий на текущей строке завершается, а на новой строке начинается новый комментарий. Если comment-multi-line отлична от nil, то новая следующая строка подготавливается как часть того же самого комментария, который находился на первой строке. Это выполняется следующим образом: в старой строке не вставляется ограничитель комментария, и в новую строку не вставляеся начало комментария. В тех языках, где работают многострочные комментарии, выбор значений для этой переменной -- дело вашего вкуса.

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

Редактирование без разбалансированных скобок

@hyphenation{s-вы-ра-же-ний}

M-(
Поставить скобки вокруг следующего s-выражения (или s-выражений) (insert-parentheses).
M-)
Передвинуться через следующую закрывающую скобку и сделать новый отступ (move-past-close-and-reindent).

Команды M-( (insert-parentheses) и M-) (move-past-close-and-reindent) созданы для облегчения такого вида редактирования, при котором скобки всегда остаются сбалансированными. M-( вставляет пару скобок, либо вместе, как в `()', либо, если задан аргумент, вокруг следующих нескольких s-выражений, и оставляет точку после открытой скобки. Точка остается после открывающей скобки. Команда M-) перемещается через закрывающую скобку, удаляя любой предшествующий ей отступ и делая после нее отступ при помощи C-j.

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

M-( может вставлять перед открывающей скобкой пробел в зависимости от синтаксического класса предыдущего знака. Установите parens-require-spaces в значение nil, если вы хотите подавить это.

Завершение для имен символов

Обычно завершение происходит в минибуфере. Но один из видов завершения доступен во всех буферах: завершение для имен символов.

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

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

В большинстве основных режимов для языков программирования, M-TAB запускает команду complete-symbol, которая предоставляет два типа завершения. Обычно она делает завершения, основываясь на таблице тегов (see section Таблицы тегов); с числовым аргументом (независимо от его зачения), она делает завершение, основываясь на именах, перечисленных в указателе понятий в Info-файле для этого языка. Поэтому чтобы завершить имя символа, определенного в вашей собственной программе, используйте M-TAB без аргумента; чтобы завершить имя стандартной библиотечной функции, используйте C-u M-TAB. Конечно, основанное на Info завершение работает, только если есть Info-файл для стандартной библиотеки функций вашего языка, и только если он установлен в вашей системе.

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

В режиме Text и родственных с ним, M-TAB завершает слова, основываясь на словаре программы проверки правописания. See section Поиск и исправление орфографических ошибок.

Режим Which Function

Режим Which Function -- это второстепенный режим, который показывает в строке режима имя текущей функции по мере того, как вы передвигаетесь по буферу.

Чтобы включить (или выключить) режим Which Function, используйте команду M-x which-function-mode. Это глобальная команда; она применяется ко всем буферам, как к существующим, так и к тем, что еще будут созданы. Однако, это затрагивает только определенные основные режимы, перечисленные в значении which-func-modes. (Если это значение t, то режим Which Function применяется ко всем основным режимам, которые знают, как это поддерживается -- к основным режимам, поддерживающим Imenu.)

Команды документации

Когда вы редактируете код на Лиспе, предназначенный для запуска в Emacs, вы можете использованы команды C-h f (describe-function) и C-h v (describe-variable) для печати документации о функциях и переменных, которые вы хотите вызвать. Эти команды используют минибуфер для считывания имени функции или переменной и показывают документацию в окне.

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

Для кода на Emacs Lisp вы также можете использовать режим Eldoc. Этот второстепенный режим постоянно показывает в эхо-области список аргументов для функции, которая вызывается в точке. (Другими словами, он находит вызов функции, который содержит точку, и показывает список аргументов этой функции.) Режим Eldoc применим только к режимам Emacs Lisp и Lisp Interaction. Для включения и выключения этого режима используйте команду M-x eldoc-mode.

Для Си, Лиспа и других языков вы можете использовать C-h C-i (info-lookup-symbol), чтобы просмотреть документацию Info по какому-то символу. Вы задаете символ в минибуфере; по умолчанию берется символ, находящийся в буфере в точке. Где искать документацию по символам -- в каких Info-файлах и каких именных указателях --- определяет основной режим. Вы можете также использовать M-x info-lookup-file для нахождения документации для имени файла.

Вы можете прочитать "страницу man" для команды операционной системы, библиотечной функции или системного вызова с помощью команды M-x manual-entry. Для форматирования страницы она запускает программу @command{man} и, если позволяет ваша операционная система, делает это асинхронно, чтобы вы могли продолжать редактирование, пока страница форматируется. (MS-DOS и MS-Windows 3 не допускают асинхронных подпроцессов, так что на этих системах вы не можете редактировать, когда Emacs ожидает, пока @command{man} закончит работу.) Результат направляется в буфер с именем `*Man тема*'. Эти буферы используют особый основной режим, режим Man, который облегчает прокрутку и просмотр других страниц man. Для получения подробностей наберите C-h m в буфере страницы man.

Для длинных страниц правильная установка начертаний может занять значительное время. По умолчанию Emacs использует в страницах man начертания, если может показывать разные шрифты или цвета. Вы можете выключить использование разных начертаний в страницах man, установив переменную Man-fontify-manpage-flag равной nil.

Если вы вставите текст страницы man в буфер Emacs каким-то другим способом, вы можете использовать команду M-x Man-fontify-manpage, чтобы произвести те же преобразования, что делает M-x manual-entry.

Проект GNU надеется когда-нибудь заменить большинство страниц man на лучше организованные руководства, которые вы можете просматривать с помощью Info. See section Другие команды для получения справки. Поскольку этот процесс завершен лишь частично, читать страницы man все еще полезно.

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

Команда Emacs C-x 4 a добавляет в журнал изменений новую запись для файла, который вы редактируете (add-change-log-entry-other-window).

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

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

1993-05-25  Richard Stallman  <rms@gnu.org>

        * man.el: Rename symbols `man-*' to `Man-*'.
        (manual-entry): Make prompt string clearer.

        * simple.el (blink-matching-paren-distance):
        Change default to 12,000.

1993-05-24  Richard Stallman  <rms@gnu.org>

        * vc.el (minor-mode-map-alist): Don't use it if it's void.
        (vc-cancel-version): Doc fix.

(Предыдущие версии Emacs использовали другой формат даты.)

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

C-x 4 a обращается к файлу журнала изменений и создает новую запись, если только последний по времени пункт не датирован сегодняшним днем и не несет ваше имя. Также она создает новый пункт для текущего файла. Для многих языков она может даже предположить имя измененной функции или объекта.

К файлу журнала изменений обращаются в режиме Change Log. В этом основном режиме каждая связка сгруппированных пунктов считается одним абзацем, а каждая запись считается страницей. Это облегчает редактирование записей. C-j и автоматическое заполнение делают в каждой новой строке такой же отступ, как в предыдущей; это удобно для ввода содержимого записей.

Системы управления версиями дают другой способ отслеживания изменений в вашей программе и ведения журнала изменений. See section Буфер журнальной записи.

Таблицы тегов

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

Таблицы тегов хранятся в файлах, именуемых файлами таблиц тегов. Общепринятое имя для файла таблицы тегов -- `TAGS'.

Каждый элемент в таблице тегов записывает имя одного тега, имя файла, в котором этот тег определен (явно), и местоположение определения тега в этом файле.

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

Синтаксис тегов исходного файла

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

  • В программе на Си, любая функция Си или typedef -- это тег, тегом являются и определения struct, union и enum. Определения макросов (#define) и констант (enum) также являются тегами, если только вы не задали при создании таблицы тегов ключ @option{--no-defines}. Аналогично, тегами являются глобальные переменные, если только вы не задали ключ @option{--no-globals}. Использование @option{--no-globals} и @option{--no-defines} может сделать файлы таблиц тегов гораздо меньше.
  • В коде на Си++, помимо всех тегов кода Си распознаются также функции-члены и, возможно, переменные-члены, если вы используете ключ @option{--members}. Теги для переменных и функций в классах именуются как `класс::переменная' и `класс::функция'.
  • В коде на Java, теги включают все конструкции, распознаваемые в Си++ плюс конструкции extends и implements. Теги для переменных и функций в классах именуются как `класс.переменная' и `класс.функция'.
  • В тексте для LaTeX, тегами служат аргументы каждой из команд \chapter, \section, \subsection, \subsubsection, \eqno, \label, \ref, \cite, \bibitem, \part, \appendix, \entry или \index. Другие команды тоже могут создавать теги, если вы укажете их в переменной среды @env{TEXTAGS} перед вызовом @command{etags}. Значением этой переменной среды должен быть разделенный двоеточиями список имен команд.
    TEXTAGS="def:newcommand:newenvironment"
    export TEXTAGS
    
    задает (с использованием синтаксиса Bourne shell), что команды `\def', `\newcommand' и `\newenvironment' также определяют теги.
  • В коде на Лиспе любая функция, определенная через defun, любая переменная, определенная через defvar или defconst, и вообще первый аргумент любого выражения, которое начинается с `(def' в нулевом столбце, являются тегом.
  • В коде на Scheme теги включают все определяемое с помощью def или конструкции, чье имя начинается с `def'. Они также включают переменные, установленные с помощью set! на верхнем уровне файла.

Поддерживаются также несколько других языков:

  • В коде ассемблера, теги -- это метки, появляющиеся в начале строки, за которыми идет двоеточие.
  • Во входных файлах Bison или Yacc каждое правило определяет конструируемый им нетерминал как тег. Части файла, содержащие код на Си, анализируются как код Си.
  • В коде на Cobol тегами служат имена параграфов; то есть любые слова, которые начинаются в столбце 8, и после которых стоит точка.
  • В коде на Erlang тегами служат определенные в файле функции, записи и макросы.
  • В Фортран-коде тегами являются функции, подпрограммы и блоки данных.
  • В коде на Паскале тегами будут определенные в файле функции и процедуры.
  • В коде на Perl тегами являются процедуры, определяемые ключевым словом sub.
  • В коде на Postscript тегами являются функции.
  • В коде на Прологе теги появляются на левой границе.

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

Создание таблицы тегов

Для создания файла таблицы тегов используется программа @command{etags}. Она знает несколько языков, как описано в предыдущем разделе. @command{etags} запускается следующим образом:

etags входные-файлы...

Программа @command{etags} считывает указанные файлы и записывает таблицу тегов под именем `TAGS' в текущем рабочем каталоге. @command{etags} распознает язык, используемый во входном файле, основываясь на имени этого файла и его содержании. Вы можете указать язык с помощью ключа `--language=имя', описанного ниже.

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

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

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

Одна таблица тегов может как бы включать другую. Имя включаемого файла тегов указывается с помощью ключа `--include=файл' при создании включающего файла. Последний файл затем ведет себя так, как если бы он содержал все файлы, заданные во включенном файле, так же как и те файлы, которые он содержит непосредственно.

Если при запуске @command{etags} вы зададите исходные файлы по относительным именам, файл тегов будет содержать имена файлов, относительные к каталогу, в котором этот файл тегов был изначально записан. Тогда вы сможете переместить все дерево каталогов, содержащее и файл тегов, и исходные файлы, и файл тегов все равно будет правильно ссылаться на исходные файлы.

Если в качестве аргументов @command{etags} вы зададите абсолютные имена файлов, то файл тегов будет содержать абсолютные имена. Тогда файл тегов будет так же ссылаться на те же исходные файлы, даже если вы переместите его, до тех пор, пока исходные файлы остаются на старом месте. Абсолютные имена файлов начинаются с `/', или с `устройство:/' в MS-DOS и MS-Windows.

Когда вы хотите создать таблицы тегов для очень большого числа файлов, у вас могут возникнуть проблемы с их перечислением в командной строке, поскольку некоторые системы накладывают ограничение на ее длину. Простейший способ обойти это ограничение -- сказать @command{etags} считывать имена файлов со стандартного ввода, набрав дефис на месте имен файлов, как здесь:

find . -name "*.[chCH]" -print | etags -

Используйте ключ @option{--language=имя} для явного указания языка. Вы можете перемешивать эти ключи с именами файлов; каждый относится к имена файла, которое следует за ним. Задайте @option{--language=auto}, чтобы велеть @command{etags} продолжать самой предполагать язык по имени и содержимому файла. Задайте @option{--language=none}, чтобы полностью выключить специфичную для языка обработку; тогда @command{etags} распознает теги только по сопоставлению с регулярным выражением. `etags --help' печатает перечень языков, которые знает @command{etags}, и правила предположения языка по имени файла.

Ключ @option{--regex} предоставляет общий способ распознавания тегов, основаный на сопоставлении с регулярным выражением. Вы можете свободно перемешивать эти ключи с именами файлов. Каждый ключ @option{--regex} добавляется к предшествующим и применяется только к последующим файлам. Синтаксис таков:

--regex=/regexp-тег[/regexp-имя]/

где regexp-тег используется для нахождения строк тегов. Оно всегда зацепленное, то есть ведет себя так, как если бы в начале стояло `^'. Если вы хотите учесть отступы, просто назовите совпадением произвольное количество пропусков, начав ваше регулярное выражение с `[ \t]*'. Знак `\' в регулярных выражениях экранирует следующий знак, а `\t' обозначает символ табуляции. Обратите внимание, @command{etags} не обрабатывает другие управляющие последовательности Си для специальных знаков.

@command{etags} придерживается того же синтаксиса регулярных выражений, что и Emacs, но с введением оператора интервала, который работает как в @command{grep} и @command{ed}. Синтаксис оператора интервала такой: `\{m,n\}', это означает, что нужно найти совпадение с предыдущим выражением по меньшей мере m раз и вплоть до n раз.

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

Ключ @option{-R} удаляет все регулярные выражения, определенные ключами @option{--regex}. Он применяется к следующим за ним именам файлов, как вы можете видеть из следующего примера:

etags --regex=/reg1/ voo.doo --regex=/reg2/ \
    bar.ber -R --lang=lisp los.er

Здесь @command{etags} выбирает язык для анализа `voo.doo' и `bar.ber' в соответствии с их содержимым. @command{etags} также использует reg1 для распознавания дополнительных тегов в `voo.doo' и оба выражения reg1 и reg2 для распознавания дополнительных тегов в `bar.ber'. Для распознавания тегов в `los.er' @command{etags} использует правила тегов для Лиспа и не использует регулярные выражения.

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

  • Сделать теги для макроса DEFVAR в исходных файлах Emacs:
    --regex='/[ \t]*DEFVAR_[A-Z_ \t(]+"\([^"]+\)"/'
    
  • Сделать теги для VHDL-файлов (этот пример -- одна строка, разбитая здесь для правильного форматирования):
    --language=none
    --regex='/[ \t]*\(ARCHITECTURE\|CONFIGURATION\) +[^ ]* +OF/'
    --regex='/[ \t]*\(ATTRIBUTE\|ENTITY\|FUNCTION\|PACKAGE\
    \( BODY\)?\|PROCEDURE\|PROCESS\|TYPE\)[ \t]+\([^ \t(]+\)/\3/'
    
  • Сделать теги для файлов на Tcl (этот последний пример показывает использование аргумента regexp-имя):
    --lang=none --regex='/proc[ \t]+\([^ \t]+\)/\1/'
    

Чтобы получить перечень других доступных ключей @command{etags}, выполните @command{etags --help}.

Выбор таблицы тегов

Emacs хранит в каждый момент одну выбранную таблицу тегов, и все команды для работы с таблицами тегов используют эту выбранную таблицу. Чтобы выбрать таблицу тегов, наберите M-x visit-tags-table, которая считает имя файла таблицы тегов как аргумент. Имя `TAGS' в каталоге по умолчанию используется как имя файла по умолчанию.

Все, что делает эта команда, -- сохраняет имя файла в переменной tags-file-name. Emacs фактически не считывает содержимое таблицы тегов до тех пор, пока вы не попытаетесь использовать его. Самостоятельная установка этой переменной так же хороша, как и использование visit-tags-table. Начальное значение переменной равно nil; это значение сообщает всем командам для работы с таблицами тегов, что они должны запрашивать, какое имя файла таблицы тегов надо использовать.

Использование visit-tags-table, когда таблица тегов уже загружена, дает вам выбор: вы можете добавить новую таблицу тегов к текущему списку таких таблиц или начать новый список. Команды работы с тегами используют все таблицы тегов в текущем списке. Если вы начинаете новый список, новая таблица тегов используется вместо остальных. Если вы добавляете новую таблицу тегов к текущему списку, она используется вместе с остальными. Когда команды работы с тегами сканируют список таблиц тегов, они не всегда начинают с начала списка; они начинают с первой таблицы, которая описывает текущий файл (если такая есть), проходят далее до конца списка и затем просматривают список с начала до тех пор, пока в нем не будут проверены все таблицы.

Вы можете явно задать список таблиц тегов, установив переменную tags-table-list в значение списка строк, как показано:

(setq tags-table-list
      '("~/emacs" "/usr/local/lib/emacs/src"))

Это заставляет команды, работающие с тегами, просматривать файлы `TAGS' в каталогах `~/emacs' и `/usr/local/lib/emacs/src'. Порядок зависит от того, в каком файле вы сейчас находитесь и какая таблица тегов упоминает этот файл, как обяснено выше.

Не установливайте переменные tags-file-name и tags-table-list одновременно.

Поиск определения тега

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

M-. тег RET
Найти первое определение тега (find-tag).
C-u M-.
Найти следующее по очереди определение последнего заданного тега.
C-u - M-.
Вернуться к предыдущему найденному тегу.
C-M-. образец RET
Найти тег, чье имя совпадает с образцом (find-tag-regexp).
C-u C-M-.
Найте следующий тег, чье имя совпадает с последним использованным образцом.
C-x 4 . тег RET
Найте первое определение тега, но показать его в другом окне (find-tag-other-window).
C-x 5 . тег RET
Найте первое определение тега и создать новый фрейм для выбора буфера (find-tag-other-frame).
M-*
Вернуться к тому месту, где вы ранее вызвали M-. и товарищей.

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

Если задается пустой аргумент (просто RET), то в качестве имени тега, который надо найти, используется s-выражение, находящееся в буфере перед или вокруг точки. Для получения информации о s-выражениях смотрите section Списки и s-выражения,

Аргумент для M-. не обязан быть полным именем тега; достаточно части. Это возможно, потому что M-. находит в таблице теги, которые содержат тег как построку. Однако, она предпочитает точное совпадение совпадению лишь построки. Чтобы найти другие теги, которые соответствуют той же подстроке, следует дать find-tag числовой аргумент, как в C-u M-.; эта команда не считываает имя тега, но продолжает поиск по тексту таблицы тегов другого тега, содержащего самую последнюю использованную подстроку. Если у вас есть настоящая клавиша META, то M-0 M-. может служить более простой альтернативой C-u M-..

Подобно большинству команд, которые могут переключать буферы, find-tag имеет вариант, который показывает новый буфер в другом окне, и еще один, который создает новый фрейм. Первая команда -- это C-x 4 ., которая вызывает функцию find-tag-other-window. Вторая, C-x 5 ., вызывает find-tag-other-frame.

Чтобы вернуться к местам, где вы недавно находили теги, используйте C-u - M-.; в более общем виде, M-. с отрицательным числовым аргументом. Эта команда может перенести вас в другой буфер. C-x 4 . с отрицательным аргументом находит предыдущее положение тега в другом окне.

Так же, как вы можете вернуться к местам, где вы недавно находили теги, вы можете вернуться к местам, откуда вы их нашли. Используйте для этого M-*, что вызывает команду pop-tag-mark. Типичное применение этих команд -- найти и изучить определение чего-то с помощью M-. и затем вернуться к тому месту, где вы были, с помощью M-*.

И C-u - M-., и M-* позволяют вам пошагово проходить назад до глубины, определяемой переменной find-tag-marker-ring-length.

Команда C-M-. (find-tag-regexp) обращается к тегам, соответствующим заданному регулярному выражению. Она похожа на M-., но производит сопоставление с регулярным выражением, а не со строкой.

Поиск и замена при помощи таблиц тегов

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

M-x tags-search RET regexp RET
Поиск regexp во всех файлах в выбранной таблице тегов.
M-x tags-query-replace RET regexp RET замена RET
Осуществить query-replace-regexp в каждом файле в выбранной таблице тегов.
M-,
Перезапустить одну из вышеупомянутых команд из текущего положения точки (tags-loop-continue).

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

Найдя одно соответствие, вы, вероятно, захотите найти все остальные. Чтобы найти еще одно соответствие, наберите M-, (tags-loop-continue), это возобновит tags-search. Эта команда просматривает остаток текущего буфера и затем оставшиеся файлы таблицы тегов.

M-x tags-query-replace осуществляет во всех файлах в таблице тегов единую замену регулярного выражения с подтверждением. Она считывает регулярное выражение, которое следует искать, и строку для замены, точно так же, как обычная M-x query-replace-regexp. Она ищет очень похоже на M-x tags-search, но с повторами, обрабатывая совпадения согласно вашему вводу. See section Команды замены, более подробную информацию о замене с подтверждением.

Можно пройти по всем файлам в таблице тегов с помощью едиственного вызова M-x tags-query-replace. Но иногда бывает полезно временно выйти, что вы можете сделать с помощью любого события ввода, не имеющего особого смысла при замене с подтверждением. Вы можете впоследствии возобновить замену с подтверждением, набрав M-,; эта команда возобновляет последнюю сделанную вами команду поиска или замены тегов.

Команды этого раздела приводят к гораздо более широкому поиску, чем семейство find-tag. Команды find-tag ищут только определения тегов, совпадающих с вашей подстрокой или регулярным выражением. Команды tags-search и tags-query-replace находят каждое вхождение регулярного выражения, как делают в текущем буфере обычные команды поиска и замены.

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

Вас, возможно, поразило, что tags-search очень похожа на @command{grep}. Вы можете также запустить саму @command{grep} как подчиненную Emacs, и Emacs покажет вам совпадающие строки одну за другой. Это работает во многом похоже на запуск компиляции; обращение к тем позициям в исходных файлах, где @command{grep} нашла совпадения, работает как обращение к ошибкам компиляции. See section Запуск компиляторов в Emacs.

Запросы к таблице тегов

M-x list-tags RET файл RET
Показать список тегов, определенных в заданном файле с текстом программы.
M-x tags-apropos RET regexp RET
Показать список всех тегов, соответствующих регулярному выражению regexp.

M-x list-tags считывает имя одного из файлов, описанных в выбранной таблице тегов, и показывает список всех тегов, определенных в этом файле. Аргумент "имя файла" фактически является просто строкой для сравнения с именами, записанными в таблице тегов; он считывается как строка, а не как имя файла. Поэтому завершение и значение по умолчанию невозможны, и вы должны вводить имя файла в том же самом виде, в котором оно появляется в таблице тегов. Не включайте каталог как часть имени файла, если имя файла, записанного в таблице тегов, не включает каталог.

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

Вы также можете производить в буфере завершение в пространстве имен, составленном из имен тегов текущих таблиц. See section Завершение для имен символов.

Объединение файлов с помощью Emerge

Нередко программисты перебегают друг другу дорогу и изменяют одну и ту же программу в двух разных направлениях. Чтобы справиться с этой путаницей, вам необходимо объединить две эти версии. Emerge упрощает это. Смотрите также section Сравнение файлов, о командах для сравнения файлов более ручным методом, и @ref{Emerge,,, @external{ediff}, The Ediff Manual}.

Обзор Emerge

Чтобы запустить Emerge, выполните одну из этих четырех команд:

M-x emerge-files
Объединяет два заданных файла.
M-x emerge-files-with-ancestor
Объединяет два заданных файла, со ссылкой на общего предка.
M-x emerge-buffers
Объединяет два буфера.
M-x emerge-buffers-with-ancestor
Объединяет два буфера со ссылкой на общего предка в третьем буфере.

Команды Emerge сравнивают два файла или буфера и отображают результат сравнения в трех буферах: по одному на каждый входной файл (буфер A и буфер B) и один (буфер объединения), где объединение и происходит. Буфер объединения показывает весь объединяемый текст, а не только различия. Везде, где буферы различаются, вы можете выбрать тот, из которого вы хотите внести фрагмент.

Команды Emerge, которые принимают ввод из существующих буферов, используют только их доступные части, если эти буферы сужены (see section Сужение).

Если доступна общая начальная версия, от которой происходят оба сливаемых текста, Emerge может использовать ее, чтобы вывести предположение о том, какая из альтернатив правильна. Когда одна из текущих версий находится в согласии с предком, Emerge предполагает, что другая текущая версия -- это обдуманное изменение, которое должно сохраниться в объединенной версии. Если вы хотите указать общий начальный текст, используйте команды `with-ancestor'. Эти команды считывают три файла или имени буфера -- вариант A, вариант B и их общего предка.

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

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

В любой момент времени внимание Emerge сосредоточено на одном конкретном изменении, называемом выделенным. Это изменение помечается в трех буферах таким образом:

vvvvvvvvvvvvvvvvvvvv
различающийся текст
^^^^^^^^^^^^^^^^^^^^

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

Обычно буфер объединения изначально содержит версию A текста. Но когда версия A изменения согласуется с общим предком, для этого изменения предпочтение отдается версии B.

Когда вы выходите, Emerge оставляет объединенный текст в буфере объединения. Тогда вы можете сохранить его с помощью C-x C-w. Если вы задали emerge-files или emerge-files-with-ancestor числовой аргумент, эти команды считает имя выходного файла в минибуфере. (Это последнее имя, которое они считывают.) Тогда при выходе из Emerge объединенный текст сохраняется в выходном файле.

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

Подрежимы Emerge

Вы можете выбирать из двух режимов для отдания команд объединения: режим Fast и режим Edit. В режиме Fast основные команды объединения --- это одиночные знаки, но обычные команды Emacs выключены. Это удобно, если вы используете только команды объединения. В режиме Edit все команды объединения начинаются с префикса C-c C-c, и доступны также обычные команды Emacs. Это позволяет редактировать буфер объединения, но замедляет операции Emerge.

Используйте e, чтобы переключится в режим Edit, и C-c C-c f, чтобы переключится в режим Fast. Строка режима изображает режимы Edit и Fast при помощи `E' и `F'.

Emerge имеет два дополнительных подрежима, которые затрагивают способ работы определенных команд объединения: режим Auto Advance и режим Skip Prefers.

Если действует режим Auto Advance, команды a и b продвигают к следующему различию. Это позволяет вам быстрее сделать объединение, поскольку вы просто выбираете одну из входных альтернатив. Строка режима изображает режим Auto Advance как `A'.

Если действует режим Skip Prefers, команды n и p пропускают различия в состояниях prefer-A и prefer-B (see section Состояние различия). Таким образом, вы видите только те различия, для которых ни одна из версий не предполагается "правильной". Строка режима изображает режим Skip Prefers с помощью `S'.

Используйте команду s a (emerge-auto-advance-mode), чтобы установить или сбросить режим Auto Advance. Используйте s s (emerge-skip-prefers-mode), чтобы установить или сбросить режим Skip Prefers. Эти команды включают режим, если им задан положительный аргумент, выключают при отрицательном аргументе и переключают режим, если аргумент не задан.

Состояние различия

Различия в буфере объединения помечаются строками знаков `v' и `^'. Каждое различие имеет одно из семи следующих состояний:

A
Различие показывает версию A. Команда a всегда производит это состояние; строка режима отображает его как `A'.
B
Различие показывает версию B. Команда b всегда производит это состояние; строка режима отображает его как `B'.
default-A
default-B
Различие показывает версию A или B по умолчанию, потому что вы не сделали выбор. Все различия изначально имеют состояние default-A (и таким образом, буфер объединения -- это копия буфера A), кроме тех, для которых "предпочтительна" другая альтернатива (смотрите ниже). Когда вы выбираете различие, его состояние заменяется из default-A или default-B на простое A или B. Таким образом, выбранное различие никогда не находится в состоянии default-A или default-B, и эти состояния никогда не отображаются в строке режима. Команда d a выбирает в качестве состояния по умолчанию default-A, а d b выбирает default-B. Это состояние по умолчанию применяется ко всем различиям, которые вы никогда не выбирали и для которых нет предпочтительной альтернативы. Если вы продвигаетесь последовательно, то различия, которые вы не выбирали, -- это те, что находятся после выбранного. Таким образом, продвигаясь последовательно, вы можете в результате сделать A версией по умолчанию для некоторых фрагментов буфера объединения, а B -- версией по умолчанию для остальных фрагментов, используя между различиями d a и d b.
prefer-A
prefer-B
Различие показывает состояние A или B, потому что оно предпочтительно. Это означает, что вы не сделали явного выбора, но похоже на то, что верна одна из альтернатив, так как вторая согласуется с общим предком. Значит, когда буфер A находится в согласии с общим предком, предпочтительна версия B, потому что скорее всего это и есть действительное изменение. Эти состояния показываются в строке режима как `A*' и `B*'.
combined
Различие показывает комбинацию состояний A и B, как результат команд x c или x C. Когда различие имеет это состояние, команды a и b не делают для него ничего, если только вы не зададите им числовой аргумент. Строка режима показывает это состояние как `comb'.

Команды объединения

Это команды объединения для режима Fast; в режиме Edit предваряйте их набором C-c C-c:

p
Выбирает предыдущее различие.
n
Выбирает следующее различие.
a
Выбирает версию A этого различия.
b
Выбирает версию B этого различия.
C-u n j
Выбирает различие номер n.
.
Выбирает различие, содержащее точку. Вы можете использовать эту команды в буфере объединения или в буферах A и B.
q
Выход -- завершает объединение.
C-]
Прерывание -- выходит и не сохраняет вывод.
f
Переход в режим Fast. (В режиме Edit это на самом деле C-c C-c f.)
e
Переход в режим Edit.
l
Центирирует (как C-l) все три окна.
-
Задает часть префиксного числового аргумента.
цифра
Также задает часть префиксного числового аргумента.
d a
Выбирает A как версию по умолчанию для буфера объединения начиная с этого места.
d b
Выбирает B как версию по умолчанию для буфера объединения начиная с этого места.
c a
Копирует версию A этого различия в список уничтожений.
c b
Копирует версию B этого различия в список уничтожений.
i a
Вставляет версию A этого различия в точке.
i b
Вставляет версию B этого различия в точке.
m
Помещает точку и метку вокруг этого различия.
^
Прокручивает все три окна вниз (как M-v).
v
Прокручивает все три окна вверх (как C-v).
<
Прокручивает все три окна влево (как C-x <).
>
Прокручивает все три окна вправо (как C-x >).
|
Переустанавливает горизонтальную прокрутку во всех трех окнах.
x 1
Сужает окно объединения до одной строки. (Используйте C-u l, чтобы восстановить его полный размер.)
x c
Комбинирует две версии этого различия (see section Комбинирование двух версий).
x f
Показывает имена файлов/буферов, с которыми работает Emerge, в окне справки. (Используйте C-u l, чтобы восстановить окна.)
x j
Сцепляет это различие со следующим. (C-u x j сцепляет это различие с предыдущим.)
x s
Разбивает это различие на два. До того, как применить эту команду, расположите точку в каждом их буферов в том месте, где вы хотите разбить различие.
x t
Выбрасывает одинаковые строки сверху и снизу различия. Такие строки появляются, когда версии A и B идентичны, но отличаются от первоначальной версии.

Выход из Emerge

Команда q (emerge-quit) завершает объединение, записывая результаты в выходной файл, если вы его задали. Она восстанавливает правильное содержимое буферов A и B или уничтожает их, если они были созданы Emerge, и вы не изменяли их. Она также выключает в буфере объединения команды Emerge, поскольку выполнение их теперь может повредить содержимое различных буферов.

C-] прерывает объединение. Это означает выход без записи выходного файла. Если вы не указали выходной файл, то между прерыванием и завершением объединения на самом деле нет разницы.

Если команды Emerge были вызваны из другой программы на Лиспе, то в случае успешного завершения возвращается значение t, а если вы прервали объединение, возвращается nil.

Комбинирование двух версий

Иногда вы хотите сохранить оба варианта некоторого изменения. Чтобы сделать так, используйте x c, которая редактирует буфер объединения следующим образом:

#ifdef NEW
версия из буфера A
#else /* not NEW */
версия из буфера B
#endif /* not NEW */

Хотя этот пример показывает условные конструкции препроцессора Си, разделяющие два альтернативные версии, вы можете задать используемые строки, устанавливая переменную emerge-combine-versions-template по вашему выбору. В этой строке `%a' говорит, где нужно помещать версию A, а `%b' говорит, говорит помещать версию B. Установка по умолчанию, которая выдает результат, показанный выше, выглядит следующим так:

"#ifdef NEW\n%a#else /* not NEW */\n%b#endif /* not NEW */\n"

Тонкие вопросы, связанные с Emerge

В процессе объединения вы не должны пытаться редактировать буферы A и B сами. Emerge временно изменяет их, но в конце возвращает в исходное состояние.

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

Запуск Emerge может занять продолжительное время, поскольку ей требуется полностью сравнить файлы. Emacs не можете ничего делать, пока @command{diff} не завершится. Возможно, в будущем кто-то изменит Emerge так, что она будет делать сравнение в фоновом режиме, когда входные файлы велики -- тогда вы могли бы продолжать в Emacs другие дела, пока Emerge действительно не будет готова принимать команды.

После подготовки объединения Emerge запускает ловушку emerge-startup-hook (see section Ловушки).

Режим C и родственные с ним

Этот раздел описывает особые средства, доступные в режимах C, C++, Objective-C, Java, CORBA IDL и Pike. Когда мы говорим "режим C и родственные с ним", мы имеем в виду эти режимы.

Команды перемещения в режиме C

Этот раздел описывает команды для перемещения точки в режиме C и родственных с ним режимах.

C-c C-u
Перемещает точку назад к содержащей ее условной констукции препроцессора, оставляя метку в текущей позиции. Префиксный аргумент работает в качестве счетчика повторов. С отрицательным аргументом, перемещает точку вперед к концу этой условной констукции препроцессора. При проходе назад, #elif рассматривается как #else, за которой стоит #if. При проходе вперед #elif игнорируется.
C-c C-p
Перемещает точку назад через условную констукцию препроцессора, оставляя метку в текущей позиции. Префиксный аргумент служит в качестве счетчика повторов. С отрицательным аргументом, перемещает вперед.
C-c C-n
Перемещает точку вперед через условную констукцию препроцессора, оставляя метку в текущей позиции. Префиксный аргумент служит в качестве счетчика повторов. С отрицательным аргументом, перемещает назад.
M-a
Перемещает точку к началу самого внутреннего оперетора Си (c-beginning-of-statement). Если точка уже находится в начале оператора, перемещает к началу предыдущего. С префиксным аргументом n, перемещает назад на n - 1 операторов. Если точка находится внутри строки или комментария или после комментария (между ними только пропуск), эта команда перемещает по предложениям, а не по операторам. Если эта функция вызвана из программы, она принимает три необязательных аргумента: префиксный числовой аргумент, предел позиции в буфере (не перемещаться назад далее этой позиции) и флаг, который говорит, нужно ли двигаться по предложениям внутри комментария.
M-e
Перемещает точку к концу самого внутреннего оперетора Си; как M-a, но перемещает в противоположном направлении (c-end-of-statement).
M-x c-backward-into-nomenclature
Перемещает точку назад к началу секции или слова в нотации Си++. С префиксным аргументом n, перемещает n раз. Если n отрицательно, перемещает вперед. Нотация Си++ обозначает запись имен символов в стиле ИменованиеСимволовВСмешанномРегистреИБезПодчерков; каждая заглавная буква начинает секцию или слово. В проекте GNU мы рекомендуем использовать для разделения слов в идентификаторах Си или Си++ подчерки, а не изменение регистра.
M-x c-forward-into-nomenclature
Перемещает точку назад к концу секции или слова в нотации Си++. С префиксным аргументом n, перемещает n раз.

Электрик-знаки в Си

В режиме Си и родственных с ним некоторые печатные знаки являются "электрическими" -- помимо вставки самих себя, они также обновляют отступ в текущей строке и могут вставлять переводы строк. Это средство управляется переменной c-auto-newline. "Электрик"-знаки --- это {, }, :, #, ;, ,, <, >, /, *, ( и ).

Электрик-знаки вставляют переводы строк, только если включено средство auto-newline (это отображается в строке режима как `/a' после имени режима). Это средство управляется переменной c-auto-newline. Вы можете включить или выключить его командой C-c C-a:

C-c C-a
Перекючает автоматическую вставку переводов строк (c-toggle-auto-state). С префиксным аргументом, эта команда включает такую возможность, если аргумент положителен, и выключает, если аргумент отрицателен.

Двоеточие -- это электрик-знак, поскольку это подходит для одного двоеточия. Но это неудобно, когда вы хотите вставить двойное двоеточие в Си++. Вы можете вставить двойное двоеточие в Си++ без вставки отступа или перевода строки, набирая C-c :.

C-c :
Вставляет в точке оператор области видимости, двойное двоеточие, не изменяя отступ строки и не добавляя новых строк (c-scope-operator).

Электрик-ключ # обновляет отступ строки, если он оказался в начале директивы препроцессора. Это происходит, когда значение c-electric-pound-behavior равно (alignleft). Вы можете выключить эту возможность, устанавливая c-electric-pound-behavior в nil.

Переменная c-hanging-braces-alist управляет вставкой переводов строк до и после вставленных фигурных скобок. Это ассоциативный список с элементами в такой форме: (синтаксический-символ . список-пс). Большинство синтаксических символов, перечисленных в c-offsets-alist, имеют смысл и здесь.

Список список-пс может содержать один из символов before и after, либо оба, или это может быть nil. Когда вставляется фигурная скобка, в c-hanging-braces-alist ищется определяемый ей синтаксический контекст; если он найден, используется список-пс для выяснения того, где нужно вставить перевод строки: перед фигурной скобкой, после нее или и до, и после. Если ничего не найдено, по умолчанию вставляет перевод строки до и после фигурных скобок.

Переменная c-hanging-colons-alist управляет вставкой переводов строк до и после вставленных двоеточий. Это ассоциативный список, чьи элементы имеют форму (синтаксический-символ . список-пс). Список список-пс может содержать любые из символов before или after, либо оба, или это может быть nil.

Когда вставляется двоеточие, в этом cписке ищется определяемый им синтаксический символ, и если он найден, используется список-пс для выяснения того, где нужно вставить перевод строки: перед двоеточия, после него или и там, и там. Если этот символ не найден в списке, переводы строк не вставляется.

Электрик-знаки могут также автоматически удалять переводы строк, когда включено средство для их автоматической вставки. Это делает автоматическую вставку переводов строк более приемлимой, путем удаления переводов строк в большинстве случаев, когда это было бы желательно; устанавливая переменную c-cleanup-list, вы можете указать в каких случаях это происходить. Значение этой переменной -- это список символов, каждый из которых описывает один случай возможного удаления перевода строки. Вот перечень воспринимаемых символов и их значений:

brace-catch-brace
Сжимает конструкцию `} catch (условие) {', помещаяя ее целиком на одну строку. Сжатие происходит, когда вы набираете `{', если между фигурными скобками нет ничего, кроме catch и условия.
brace-else-brace
Сжимает конструкцию `} else {', помещаяя ее целиком на одну строку. Сжатие происходит, когда вы набираете `{' после else, но только если между фигурными скобками и else нет ничего, кроме пропусков.
brace-elseif-brace
Сжимает конструкцию `} else if (...) {', помещаяя ее целиком на одну строку. Сжатие происходит, когда вы набираете `{', если между `}' и `{' нет ничего, кроме пропусков, не считая эти ключевые слова и условие для if.
empty-defun-braces
Сжимает фигурные скобки пустого определения функции, помещая их на одну строку. Сжатие происходит, когда вы набираете закрывающую фигурную скобку.
defun-close-semi
Сжимает двоеточие и struct или подобный тип объявления, помещая двоеточие на ту же строку, где стоит закрывающая фигурная скобка. Сжатие происходит, когда вы вводите двоеточие.
list-close-comma
Сжимает запятые, следующие после фигурных скобок в массивах и сложных инициализациях. Сжатие происходит, когда вы набираете запятые.
scope-operator
Сжимает двойное двоеточие, которое может обозначать оператор области видимости в Си++, помещая эти двоеточия вместе. Сжатие происходит, когда вы набираете второе двоеточие, но только если они разделены только пропуском.

Средство голодного удаления в Си

Когда включено средство голодного удаления (это показывается в строке режима как `/h' или `/ah' после имени режима), одна команда DEL удаляет весь предшествующий пропуск, а не только одни пробел. Чтобы включать и выключать эту возможность, используйте C-c C-d:

C-c C-d
Включает или выключает средство голодного удаления (c-toggle-hungry-state). С префиксным аргументом, эта команда включает такую возможность, если аргумент положителен, и выключает, если аргумент отрицателен.
C-c C-t
Переключает средства автоматической вставки перевода строки и голодного удаления одновременно (c-toggle-auto-hungry-state).

Переменная c-hungry-delete-key говорит, включено ли средство голодного удаления.

Другие команды режима C

C-M-h
Помещает метку в конце определения функции, а точку в начале (c-mark-function).
M-q
Заполняет абзац, обрабатывая комментарии Си и Си++ (c-fill-paragraph). Если какая-либо часть текущей строки является комментарием или находится внутри комментария, эта команда заполняет этот комментарий или его абзац, сохраняя отступы и ограничители комментария.
C-c C-e
Запускает препроцессор Си для текста в области и показывает результат, который включает раскрытия всех вызовов макросов (c-macro-expand). Текст буфера, написанный перед областью, также передается препроцессору, так как там могут быть определения макросов, но вывод для этой части не показывается. Когда вы отлаживаете использующий макросы код на Си, бывает трудно точно понять, как раскрываются макросы. С этой командой вам не нужно это понимать, вы можете видеть раскрытия.
C-c C-\
Вставляет или выравнивает знаки `\' в концах строк области (c-backslash-region). Это полезно после написания или редактирования определения макроса Си. Если строка уже завершается знаком `\', эта команда подстраивает размер пропуска перед ним. В противном случае она вставляет новый `\'. Однако, последняя строка области рассматривается особо; в нее не вставляется `\', а если если этот знак там стоит, то он удаляется.
M-x cpp-highlight-buffer
Подсвечивает части текста в соответствии с условными конструкциями препроцессора. Эта команда показывает еще один буфер с именем `*CPP Edit*', который служит в качестве графического меню для выбора способа отображения конкретных видов условных конструкций и их содержимого. После изменения различных установок щелкните на `[A]pply these settings' (или перейдите в этот буфер и нажмите a), чтобы соответственно обновить подветку в буфере с режимом C.
C-c C-s
Показывает информацию о синтаксисе текущей исходной строки (c-show-syntactic-information). Это та информация, которая управляет отступом строки.

Комментарии в режимах C

Режим C и родственные режимы используют несколько переменных для управления форматом комментариев.

c-comment-only-line-offset
Дополнительный сдвиг для строки, которая содержит только начало комментария. Это может быть либо число, либо пара в форме (не-привязанный-сдвиг . привязанный-сдвиг), где не-привязанный-сдвиг -- это размер сдвига, придаваемый полнострочным комментариям, начинающимся не в нулевом столбце, а привязанный-сдвиг -- это размер сдвига, даваемый полнострочным комментариям, начинающимся в нулевом столбце. Простое число в качестве значения эквивалентно (значение . 0).
c-comment-start-regexp
Эта локальная для буфера переменная указывает, как распознавать начало комментария.
c-hanging-comment-ender-p
Если эта переменная равна nil, c-fill-paragraph оставляет завершающую строку для блока комментария на отдельной строке. Значение по умолчанию равно t, что помещает закрывающий ограничитель комментария `*/' в конце последней строки текста комментария.
c-hanging-comment-starter-p
Если эта переменная равна nil, c-fill-paragraph оставляет начинающий ограничитель блока комментария на отдельной строке. Значение по умолчанию равно t, что помещает открывающий ограничитель комментария `/*' в начале первой строки текста комментария.

Режим Fortran

Режим Fortran предоставляет специальные команды движения для операторов и подпрограмм на Фортране и команды отступов, которые понимают фортрановские соглашения о вложенности, номера строк и операторы продолжения. Режим Fortran имеет свой собственный режим Auto Fill, который обрывает длинные строки на правильные с точки зрения Фортрана строки продолжения.

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

Используйте M-x fortran-mode, чтобы переключиться в этот режим. Эта команда запускает ловушку fortran-mode-hook (see section Ловушки).

Команды движения

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

C-M-a
Переместить точку на начало подпрограммы (beginning-of-fortran-subprogram).
C-M-e
Переместить точку на конец подпрограммы (end-of-fortran-subprogram).
C-M-h
Поставить точку в начале подпрограммы, а метку в ее конце (mark-fortran-subprogram).
C-c C-n
Перейти на начало текущего или следующего оператора (fortran-next-statement).
C-c C-p
Перейти на конец текущего или предыдущего оператора (fortran-previous-statement).

Отступы в Фортране

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

Команды отступа в Фортране

TAB
Сделать отступ текущей строки (fortran-indent-line).
C-j
Сделать отступ текущей строки и начать новую строку с отступом (fortran-indent-new-line).
C-M-j
Прервать текущую строку и подготовить строку продолжения.
M-^
Соединить эту строку со следующей.
C-M-q
Сделать отступ во всех строках подпрограммы, в которой находится точка (fortran-indent-subprogram).

Режим Fortran переопределяет TAB так, чтобы он делал новый отступ в текущей строке для Фортрана (fortran-indent-line). Номера строк и маркеры продолжения имеют отступ до требуемых столбцов, а тело оператора получает независимый отступ, основанный на его вложенности в программе.

Ключ C-j запускает команду fortran-indent-new-line, которая заново делает отступ в текущей строке, а затем создает новую строку и деалет отступ в ней. Эта команда полезна для создания нового отступа в закрывающем операторе циклов `do' и других блоков перед началом новой строки.

Ключ C-M-q запускает fortran-indent-subprogram, команду для создания отступа во всех строках фортрановской подпрограммы (функции и процедуры), cодержащей точку.

Ключ C-M-j запускает fortran-split-line, которая разрывает строку соответствующим Фортрану способом. В строке, которая не является комментарием, вторая половина становится строкой продолжения и имеет соответственный отступ. В строке комментария обе половины становятся отдельными строками комментария.

M-^ запускает команду fortran-join-line, которая более или менее является обращением fortran-split-line. Она объединяет текущую и предшествующую строки подходящим для Фортрана способом.

Строки продолжения

Большиство современных компиляторов Фортрана разрешают два способа написания строк продолжения. Если первый непробельный знак на строке находится в столбце 5, то эта строка считается продолжением предыдущей. Мы называем это фиксированным форматом; (В GNU Emacs мы всегда остчитываем столбцы от нуля.) Переменная fortran-continuation-string указывает, какой знак надо помещать в столбец 5. Строка, начинающаяся со знака табуляции, за которым стоит любая цифра, кроме `0', также является строкой продолжения. Этот стиль продолжения мы называем табулированным форматом.

Режим Fortran может делать строки продолжения в обоих стилях, но вы должны указать, какой вы предпочитаете. Этим выбором управляет значение прееменной indent-tabs-mode: nil означает фиксированный формат, а отличное от nil -- табулированный. Вы можете судить о действующим в данный момент формате по наличию или отсутствию в строке режима слова `Tab'.

Если текст на строке начинается с принятого в Фортране маркера продолжения `$' или с непробельного знака в столбце 5, режим Fortran считает эту строку строкой продолжения. Когда вы делаете в строке продолжения отступ с помощью TAB, эта строка приводится к текущему стилю продолжения. Когда вы разбиваете фортрановский оператор с помощью C-M-j, на новой строке создается маркер продолжения в соотвествии с этим стилем.

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

Когда вы включаете режим Fortran для существующего файла, он старается вычислить подходящий стиль продолжения автоматически, исходя из содержимого этого файла. Выбор определяет первая строка, которая начинается с табуляции или шести пробелов. Переменная fortran-analyze-depth определяет, сколько строк нужно рассмотреть (от начала файла); если ни одна их этих строк не укажет стиль, то он определяется по переменной fortran-tab-mode-default. Если она равна nil, то используется фиксированный формат, отличное от nil значение велит использовать табулированный формат.

Номера строк

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

Номера строк из четырех и менее цифр обычно имеют отступ на один пробел. Это управляется переменной fortran-line-number-indent, значение которой является максимальным отступом, который может иметь номер строки. Номера строк получают такой отступ, чтобы они корректно оканчивались в четвертом столбце, если при этом не требуется отступ больше максимального. По умолчанию значение переменной равно 1.

Простая вставка номера строки достаточна для того, чтобы отступ у него соответствовал этим правилам. Как только вставляется каждая цифра, отступ пересчитывается. Чтобы выключить это свойство, установите переменную fortran-electric-line-number в nil. Тогда вставка номеров строк будет похожа на вставку всего остального.

Синтаксические соглашения

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

  • Два вложенных цикла `do' никогда не имеют общего оператора `continue'.
  • Ключевые слова Фортрана, такие как `if', `else', `then', `do' и другие, написаны без внутренних пробелов и разрывов строк. Компиляторы Фортрана обычно игнорируют все пробельные знаки вне строковых констант, но режим Fortran не распознает эти ключевые слова, если они разорваны. Конструкции вроде `else if' или `end do' допустимы, но второе слово должно быть на той же строке, что и первое, а не на строке продолжения.

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

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

Несколько дополнительных переменных управляют тем, как работает отступ в Фортране:

fortran-do-indent
Дополнительный отступ в пределах каждого уровня оператора `do' (по умолчанию 3).
fortran-if-indent
Дополнительный отступ в пределах каждого уровня оператора `if' (по умолчанию 3). Это же значение используется для дополнительного отступа каждого уровня оператора Фортрана90 `where'.
fortran-structure-indent
Дополнительный отступ в пределах каждого уровня операторов `structure', `union' или `map' (по умолчанию 3).
fortran-continuation-indent
Дополнительный отступ для тел строк продолжения (по умолчанию 5).
fortran-check-all-num-for-matching-do
Если это nil, команды отступа считают, что каждый оператор `do' кончается на операторе `continue'. Поэтому при вычислении отступа для оператора, отличного от `continue', они могут сократить время, не выполняя в этом месте проверку окончания оператора `do'. Если это не nil, то команды отступа для любого пронумерованного оператора должны проверять, не заканчивается ли там `do'. По умолчанию значение равно `nil'.
fortran-blink-matching-if
Если это t, создание отступа для оператора `endif' на мгновение перемещает курсор к парному оператору `if', чтобы вы видели, где он находится. По умолчанию nil.
fortran-minimum-statement-indent-fixed
Минимальный отступ для операторов Фортрана при использовании фиксированного формата для строк продолжения. Тела операторов никогда не получают отступ менее этого. По умолчанию это 6.
fortran-minimum-statement-indent-tab
Минимальный отступ для операторов Фортрана при использовании табулированного формата строк продолжения. Тела операторов никогда не получают отступ менее этого. По умолчанию это 8.

Комментарии в Фортране

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

Режим Fortran также может обрабатывать нестандартный синтаксис комментариев, когда комментарии начинаются с `!' и могут следовать за другим текстом. Так как только некоторые компиляторы Фортрана признают такой синтаксис, режим Fortran не вставляет такие комментарии, если вы не потребовали этого заранее. Чтобы сделать это, установите переменной comment-start значение `"!"' (see section Переменные).

M-;
Выровнять комментарий или вставить новый комментарий (fortran-comment-indent).
C-x ;
Применяется только к нестандартным комментариям `!'.
C-c ;
Превратить все строки области в комментарии или (с аргументом) превратить их обратно в реальный код (fortran-comment-region).

M-; в режиме Fortran переопределяется на fortran-comment-indent. Как и обычная команда M-;, она распознает любой вид существующих комментариев и соответственно выравнивает его текст; если существующего комментария нет, то комментарий вставляется и выравнивается. Но вставка и выравнивание комментариев в режиме Fortran не такие, как в других режимах.

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

Нестандартные комментарии с `!' выравниваются, как комментарии в других языках, но полнострочные комментарии выравниваются иначе. В стандартном полнострочном комментарие сам ограничитель комментария должен всегда появляться в нулевом столбце. Что может выравниваться, так это текст в пределах комментария. Вы можете выбирать из трех возможных видов выравнивания, устанавливая переменную fortran-comment-indent-style в одно из этих значений:

fixed
Текст выравнивается по фиксированному столбцу, который является суммой fortran-commenrt-line-column и минимального отступа оператора. Это значение принимается по умолчанию. Минимальный отступ операторов -- это fortran-minimum-statement-indent-fixed для стиля продолжения с фиксированным форматом и fortran-minimum-statement-indent-tab для стиля с табулированным форматом.
relative
Текст выравнивается так, как если бы он был строкой кода, но с дополнительными fortran-comment-line-column столбцами отступа.
nil
Текст в полнострочных комментариях не перемещается автоматически.

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

В режиме Fortran вводятся две переменные, comment-line-start и comment-line-start-skip, которые играют для полнострочных комментариев ту же роль, что и comment-start и comment-start-skip для обычных, следующих за текстом комментариев. Обычно они устанавливаются правильно режимом Fortran, так что их не нужно менять.

Обычная команда Emacs для создания комментария C-x ; переопределена. Если вы используете комментарии с `!', эта команда может быть использована с ними. Иначе она бесполезна в режиме Fortran.

Команда C-c ; (fortran-comment-region) превращает все строки области в комментарии, вставляя `C$$$' в начале каждой из строк. С числовым аргументом, она превращает область обратно в реальный код, удаляя `C$$$' из начала каждой строки в этой области. Строка, используемая для этих комментариев, может управляться установкой переменной fortran-comment-region. Заметим, что здесь мы имеем пример команды и переменной с одним и тем же именем. Эти два варианта использования имени никогда не конфликтуют, так как в Лиспе и в Emacs всегда понятно по контексту, какое из них имеется в виду.

Режим Fortran Auto Fill

Режим Fortran Auto Fill -- это второстепенный режим, который автоматически разбивает фортрановские операторы, когда они становятся слишом широкими по мере того, как вы их вставляете. Разбиение оператора влечет создание строки продолжения с использованием fortran-continuation-string (see section Строки продолжения). Разбиение происходит, когда вы набираете SPC, RET или TAB, а также в командах для отступов в Фортране.

M-x fortran-auto-fill-mode включает режим Fortran Auto Fill, если он был выключен, или выключает, если он был включен. Эта команда работает так же, как работает M-x auto-fill-mode для обычного режима Auto Fill (see section Заполнение текста). Положительный аргумент включает режим Fortran Auto Fill, а отрицательный выключает. Вы можете узнать, действует ли режим Fortran Auto Fill, по наличию слова `Fill' в строке режима в круглых скобках. Режим Fortran Auto Fill -- это второстепенный режим, включаемый и выключаемый в каждом буфере отдельно. See section Второстепенные режимы.

Режим Fortran Auto Fill разрывает строки на пробелах или разделителях, когда строки становятся длиннее желаемой ширины (значения fill-column). Разделителями, на которых режим Fortran Auto Fill может разорвать строку, являются `,', `'', `+', `-', `/', `*', `=' и `)'. Разрыв происходит после разделителя, если переменная fortran-break-before-delimiters равна nil. Иначе (и по умолчанию) разрыв делается перед разделителем.

По умолчанию режим Fortran Auto Fill не задействован. Если вы хотите, чтобы это средство было включено постоянно, добавьте к fortran-mode-hook функцию-ловушку, которая выполнит (fortran-auto-fill-mode 1). See section Ловушки.

Проверка столбцов в Фортране

C-c C-r
Кратковременно показать "линейку столбцов" над текущей строкой (fortran-column-ruler).
C-c C-w
Временно разделить текущее окно по горизонтали таким образом, чтобы оно стало шириной в 72 столбца. Это может помочь вам избежать выхода за лимит в 72 столбца, который накладывают некоторые компиляторы Фортрана (fortran-window-create-momentarily).

Команда C-c C-r (fortran-column-ruler) кратковременно показывает над текущей строкой линейку столбцов. Линейка столбцов --- это две строки текста, которые показывают вам позиции столбцов, имеющих специальные значения в Фортран-программах. Квадратные скобки показывают границы столбцов для номеров строк, а фигурные скобки показывают границы столбцов для тела оператора. Над ними показаны номера столбцов.

Заметьте, что номера столбцов считаются от нуля, как всегда в GNU Emacs. В связи с этим номера могут на единицу меньше, чем те, к которым вы привыкли; но указываемые ими позиции в строке стандартны для Фортрана.

Текст, используемый для показа линейки столбцов, зависит от значения переменной indent-tabs-mode. Если indent-tabs-mode равна nil, то в качестве линейки столбцов используется значение переменной fortran-column-ruler-fixed. Иначе показывается переменная fortran-column-ruler-tab. Изменяя эти переменные, вы можете изменить вид линейки столбцов.

Для еще большей помощи используйте команду C-c C-w (fortran-window-create), которая разделяет теущее окно по горизонтали, делая его ширину равной 72 столбцам. При редактировании в этом окне вы можете непосредственно видеть, когда вы сделали строку слишком длинной, чтобы она была правильной с точки зрения Фортрана.

Сокращения ключевых слов Фортрана

Режим Fortran обеспечивает множество встроенных сокращений для часто встречающихся ключевых слов и объявлений. Это те же виды сокращений, которые вы можете определить сами. Чтобы использовать их, вы должны включить режим Abbrev. See section Сокращения.

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

Например, одно встроенное фортрановское сокращение -- это `;с' для `continue'. Если вы вставите `;с' и затем поставите знаки пунктуации, например пробел или перевод строки, то `;с' автоматически изменится на `continue', при условии, что включен режим Abbrev.

Наберите `;?' или `;C-h', чтобы просмотреть все встроенные сокращения для Фортрана и то, чему они соответствуют.

Другие команды режима Fortran

C-x n d
Сужает до текущей подпрограммы Фортрана.

Режим Fortran переопределяет ключ C-x n d для запуска команды fortran-narrow-to-subprogram, которая служит фортрановским аналогом обычного определения этого ключа. Она сужает буфер до подпрограммы, содержащей точку.

Режим Asm

Режим Asm -- это основной режим для редактирования файлов на ассемблерном коде. Он определяет следующие команды:

TAB
tab-to-tab-stop.
C-j
Вставляет перевод строки и делает отступ, используя tab-to-tab-stop.
:
Вставляет двоеточие и затем удаляет отступ перед меткой, предшествующей двоеточию. Затем делает tab-to-tab-stop.
;
Вставляет или выравнивает комментарий.

Переменная asm-comment-char определяет, какой знак начинает комментарий в синтаксисе ассемблера.


Go to the first, previous, next, last section, table of contents.

Наш баннер
Вы можете установить наш баннер на своем сайте или блоге, скопировав этот код:
RSS новости