В предыдущей главе обсуждались команды Emacs, полезные для внесения изменений в программы. Эта глава имеет дело с командами, которые помогают в обширном процессе разработки и сопровождения программ.
Emacs может запускать компиляторы для недиалоговых языков, таких как Си и Фортран, как подчиненные процессы, подавая протокол ошибок в буфер Emacs. Он также может произвести разбор сообщений об ошибках и показать вам строки исходных текстов, где произошла ошибка.
grep
под управлением Emacs, перечисляя
совпавшие строки в буфере `*grep*'.
grep
через find
с предоставленными
пользователем аргументами, направляя вывод в буфер `*grep*'.
grep
.
Чтобы запустить make
или другую команду компиляции,
выполните M-x compile. Эта команда считывает командную строку
оболочки, используя минибуфер, и затем выполняет эту командную строку в
подчиненной оболочке, помещая вывод в буфер с именем
`*compilation*'. В качестве рабочего каталога для выполнения этой
команды используется каталог по умолчанию текущего буфера, следовательно,
компиляция производится в этом каталоге.
Когда считывается командная строка оболочки, появляется минибуфер,
содержащий командную строку по умолчанию; это команда, которую вы
использовали при последнем применении M-x compile. Если вы
наберете просто RET, то снова будет использована та же самая
командная строка. Для первой M-x compile по умолчанию
используется `make -k'. Значение по умолчанию берется из переменной
compile-command
; если соответствующая команда компиляции для
файла является чем-то другим, не `make -k', то может быть полезно
иметь для этого файла локальное значение compile-command
(смотрите раздел Локальные переменные в файлах).
Запуск компиляции показывает буфер `*compilation*' в другом окне, но не выбирает его. Строка режима этого буфера сообщает вам, закончилась ли компиляция, при помощи слов `run' или `exit' в круглых скобках. Вы не обязаны держать этот буфер видимым, компиляция продолжается в любом случае. Пока компиляция продолжается, в строках режима всех буферов появляется слово `Compiling'. Если это слово исчезает, компиляция закончена.
Если вы хотите видеть протокол компиляции по мере его появления, переключитесь в буфер `*compilation*' и переместите точку в его конец. Когда точка расположена в конце, новый вывод процесса компиляции вставляется перед точкой, и она остается в конце. Если точка не находится в конце этого буфера, она остается на своем месте, тогда как дальнейший вывод компиляции добавляется в конец буфера.
Если вы установите переменную compilation-scroll-output
в
значение, отличное от nil
, то буфер компиляции всегда
прокручивается, чтобы показывать вывод по мере его появления.
Чтобы прекратить процесс компиляции, выполните команду M-x
kill-compilation
. Когда процесс компиляции будет прерван, строка
режима буфера `*compilation*' изменится, и в ней будет слово
`signal' вместо `run'. Запуск новой компиляции также
уничтожает любую работающую компиляцию, так как в одно время может
существовать только одна. Однако M-x compile требует
подтверждения перед фактическим уничтожением уже запущенной компиляции.
Точно так же, как вы запускаете из Emacs компилятор, и затем
обращаетесь к строкам, где были ошибки компиляции, вы можете запустить
grep
и затем обратиться к строкам, где были найдены
совпадения. Это работает путем интерпретации сообщений о совпадениях от
grep
как сообщений об "ошибках".
Чтобы сделать это, наберите M-x grep и введите командную строку,
указывающую, как нужно запускать grep
. Используйте те же
аргументы, которые вы дали бы grep
при обычном запуске:
регулярное выражение в формате grep
(обычно в одиночных
кавычках, чтобы отменить особый смысл специальных символов оболочки), за
которым следуют имена файлов, в которых можно использовать шаблоны.
Вывод из grep
идет в буфер `*compilation*'. Вы можете
обратиться к совпавшимстрокам при помощи C-x ` и RET, как к
ошибкам компиляции.
Если вы зададите для M-x grep префиксный аргумент, она найдет в
окрестности точки тег (смотрите раздел Таблицы тегов) и поместит его в команду
grep
по умолчанию.
Команда M-x grep-find похожа на M-x grep, но предлагает
другую командную строку по умолчанию -- строку, которая запускает
find
и grep
, так что поиск производится в каждом
файле дерева каталогов. Смотрите также команду find-grep-dired
,
раздел Dired и find
.
В буфере `*compilation*' используется особый основной режим, режим Compilation, основная цель которого -- предоставить удобный способ просмотреть строку исходного текста, где случилась ошибка.
grep
.
Вы можете обратиться к исходному тексту для любого конкретного
сообщения об ошибке, переместив точку в буфере `*compilation*' к
этому сообщению и нажав RET (compile-goto-error
). Или
щелкните на этом сообщении об ошибке Mouse-2; тогда вам не
обязательно сначала переключаться в буфер `*compilation*'.
Чтобы последовательно сделать грамматический разбор сообщений
компилятора об ошибках, набирайте C-x ` (next-error
).
Знак, стоящий после C-x -- это обратная кавычка или "акцент
грав", а не обычная одиночная кавычка. Эта команда доступна во всех
буферах, а не только в буфере `*compilation*'; она показывает
следующее сообщение об ошибке вверху одного окна и текст, в котором
находится эта ошибка, в другом окне.
Когда C-x ` используется первый раз после начала компиляции, она передвигается к положению первой ошибки. Последующие использования C-x ` продвигают вниз к следующим ошибкам. Если вы обратились к файлу по какому-то сообщению об ошибке с помощью RET или Mouse-2, последующие команды C-x ` продвигаются с этого места. Когда C-x ` доходит до конца буфера и не может найти больше сообщений, она завершается неуспехом и Emacs выдает ошибку.
C-u C-x ` начинает просмотр буфера `*compilation*' сначала. Это один из способов еще раз обработать один и тот же набор ошибок.
Режим Compilation также переопределяет ключи SPC и DEL для прокрутки по целому экрану, а M-n и M-p -- для перемещения к следующему или предыдущему сообщению об ошибке. Вы также можете использовать M-{ и M-} для перемещения вверх и вниз к сообщению об ошибке для другого исходного файла.
Возможности режима Compilation также доступны во второстепенном режиме, называемом Compilation Minor. Он позволяет вам разбирать сообщения об ошибках в любом буфере, а не только в обычном буфере для вывода протокола компиляции. Для включения этого второстепенного режима наберите M-x compilation-minor-mode. Это определит ключи RET и Mouse-2 как в основном режиме Compilation.
Второстепенный режим Compilation работает в любом буфере, если содержимое этого буфера имеет понятный ему формат. В буфере Rlogin (смотрите раздел Оболочка на удаленной машине), второстепенный режим Compilation автоматически получает удаленные исходные файлы по FTP (смотрите раздел Имена файлов).
Emacs использует для команды компиляции оболочку, но ей указывается,
что она должна быть неинтерактивной. В частности, это означает, что
оболочка начинается без подсказки. Если вы обнаружите, что буфер
`*compilation*' уродуют ваши обычные подсказки оболочки, то это
значит, что вы сделали ошибку в вашем файле инициализации оболочки,
установив подсказку, не учитывая условий, когда она не должна
появляться. (Файл инициализации может называться `.bashrc',
`.profile', `.cshrc', `.shrc' или еще как-нибудь в
зависимости от используемой вами оболочки.) Файл инициализации оболочки
должен устанавливать подсказку, только если подсказка уже есть.
Покажем, как это нужно делать в csh:
if ($?prompt) set prompt = ...
А так это делается в bash:
if [ "${PS1+set}" = set ]
then PS1=...
fi
Могут быть и другие вещи, которые вы должны делать только в интерактивной оболочке. Для проверки условия интерактивного запуска вы можете использовать такой же метод.
"Операционная система" MS-DOS не поддерживает асинхронные подпроцессы; чтобы как-то обойти этот недостаток, M-x compile в MS-DOS запускает команду компиляции синхронно. Как следствие, вы должны дождаться завершения этой команды до того, как сможете сделать что-то в Emacs. Смотрите раздел Emacs и MS-DOS.
Библиотека GUD (Grand Unified Debugger(8)) предоставляет интерфейс к различным символьным отладчикам из Emacs. Мы рекомендуем отладчик GDB, который распространяется свободно, но вы также можете запускать DBX, SDB или XDB, если они у вас есть. GUD может также служить интерфейсом к отладочному режиму Perl, отладчику Python PDB и JDB, отладчику Java.
Существует несколько команд для запуска отладчика, каждая соответствует конкретной программе-отладчику.
gud-xdb-directories
для задания каталогов поиска исходных файлов.
Каждая из этих команд принимает один аргумент: командную строку для вызова отладчика. В простейшем случае, задайте просто имя исполняемого файла, который вы хотите отлаживать. Вы также можете использовать ключи, поддерживаемые вашим отладчиком. Однако шаблоны и переменные оболочки недопустимы. GUD предполагает, что первый аргумент, не начинающийся с `-', является именем исполняемого файла.
Emacs может запустить только один отладочный процесс в одно время.
Когда вы запустили отладчик с помощью GUD, он использует буфер Emacs для обычного ввода и вывода. Этот буфер называется буфером GUD. Отладчик показывает строки исходных файлов, обращаясь к ним в буферах Emacs. Стрелка (`=>') в одном из буферов указывает на исполняемую в данный момент строку. Перемещение точки в буфере не изменяет положения стрелки.
Вы можете в любое время начать редактировать исходные файлы в тех буферах, которые их показывают. Стрелка не является частью текста файла; она появляется лишь на экране. Если вы действительно изменяете исходный файл, помните, что удаление или вставка строк собьет положение стрелки; GUD не может определить, какая строка строка соответствовала номеру строки в сообщении отладчика до вашего изменения. Кроме того, чтобы ваши изменения нашли отражение в таблицах отладчика, вам обычно придется перекомпилировать и перезапустить программу.
Если вы захотите, вы можете полностью управлять процессом отладчика через его буфер, который использует вариант режима Shell. Доступны все обычные команды вашего отладчика, и вы можете использовать команды истории режима Shell для их повторения. Смотрите раздел Режим Shell.
Буфер диалога с GUD использует вариант режима Shell, так что вам доступны команды этого режима (смотрите раздел Режим Shell). Режим GUD также предоставляет команды для установки и сброса контрольных точек, для выбора фреймов стека и для пошагового прохода по программе. Эти команды доступны как в буфере GUD, так и глобально, но с разными привязками.
Команды управления контрольными точками обычно используются в буферах, обращающихся к файлам, потому что они дают способ указать где поставить или убрать контрольную точку. Вот глобальные привязки для установки контрольных точек:
Это другая специальная команда, предоставляемая GUD. Ключи, начинающиеся с C-c, доступны только в буфере диалога с GUD. Привязки ключей, начинающиеся с C-x C-a, доступны и в буфере диалога с GUD, и в исходных файлах.
gud-refresh
.
gud-step
). Если строка содержит
вызов функции, выполнение останавливается после входа в нее.
gud-next
).
gud-stepi
).
gud-cont
).
gud-remove
). Если вы
вызовите эту команду в буфере диалога с GUD, она применяется к строке,
на который в последний раз остановилась программа.
Перечисленные выше команды относятся ко всем поддерживаемым отладчикам. Если вы пользуетесь GDB или DBX (некоторыми версиями), доступны такие дополнительные команды:
gud-up
). Это
эквивалентно команде `up'.
gud-down
). Это
эквивалентно команде `down'.
Если вы пользуетесь GDB, доступны следующие привязки:
gud-gdb-complete-command
). Этот ключ
доступен только в буфере диалога с GUD и требует GDB версии 4.13 или
более поздней.
Эти команды интерпретируют числовой аргумент как счетчик повторений, если это имеет смысл.
Так как TAB служит командой завершения, вы не можете использовать ее для набора знака табуляции в качестве ввода для программы, которую вы отлаживаете в GDB. Вместо этого, чтобы ввести знак табуляции, набирайте C-q TAB.
Во время запуска GUD выполняет одну из следующих ловушек:
gdb-mode-hook
, если вы пользуетесь GDB; dbx-mode-hook
,
если вы пользуетесь DBX; sdb-mode-hook
, если вы пользуетесь SDB;
xdb-mode-hook
, если вы пользуетесь XDB; perldb-mode-hook
для отладочного режима Perl; jdb-mode-hook
для PDB;
jdb-mode-hook
для JDB. Вы можете использовать эти ловушки для
определения ваших собственных привязок ключей для буфера диалога с
отладчиком. Смотрите раздел Ловушки.
Вот удобный способ определить команду, которая посылает отладчику некоторую командную строку и устанавливает для нее привязку в буфере диалога с отладчиком:
(gud-def функция командная-строка привязка док-строка)
Это определит команду с именем функция, которая посылает
процессу отладчика командную-строку, и даст ей строку описания
док-строка. Вы можете использовать определенную таким образом
команду в любом буфере. Если привязка не равна nil
,
gud-def
также привязывает эту команду к C-c привязка
в режиме буфера GUD и к C-x C-a привязка глобально.
Командная строка может содержать определенные `%'-последовательности, которые обозначают данные, подставляемые во время вызова функции:
В Emacs есть несколько основных режимов для языков Лисп и Scheme. В них используются одни и те же команды редактирования, но разные команды для исполнения выражений Лиспа. У каждого режима свое предназначение.
Большинство команд редактирования для работы с программами на Лиспе на самом деле доступны глобально. Смотрите раздел Редактирование программ.
Лисп-программы для команд редактирования хранятся в файлах, чьи имена традиционно оканчиваются на `.el'. Это окончание сообщает Emacs, что редактировать их следует в режиме Emacs-Lisp (смотрите раздел Исполнение лисповских выражений).
Чтобы выполнить файл с кодом на Emacs Lisp, используйте M-x load-file. Эта команда считывает имя файла, используя минибуфер, и затем выполняет содержимое этого файла как Лисп-программу. Для этого нет необходимости сначала обращаться к файлу, в любом случае эта команда считывает файл таким, каким он находится на диске, а не как текст в буфере Emacs.
Если файл Лисп-программы установлен в каталогах с библиотеками Emacs
Lisp, пользователи могут загрузить его, используя M-x
load-library. Программы могут загрузить его, вызывая
load-library
, или с помощью load
, более низкоуровневой
функции, которая похожа на эту, но допускает некоторые дополнительные
аргументы.
M-x load-library отличается от M-x load-file тем, что она просматривает последовательность каталогов и пробует три имени в каждом из них. Предположим, ваш аргумент -- это lib; три этих имени --- это `lib.elc', `lib.el' и наконец просто `lib'. Если существует файл `lib.elc', по соглашению это файл, получаемый в результате компиляции; лучше загрузить скомпилированный файл, так как он загружается и работает быстрее.
Если load-library
обнаружит, что `lib.el' новее, чем
`lib.elc', она напечатает сообщение, потому что это похоже на
то, что кто-то внес изменения в `.el'-файл и забыл его
перекомпилировать.
Так как аргумент для load-library
обычно не является сам по
себе действительным именем файла, то завершение имени файла недоступно.
Действительно, используя эту команду, вы не знаете точно, какое имя
файла будет использовано.
Последовательность каталогов, просматриваемых M-x load-library,
определяется переменной load-path
, списком строк, являющихся
именами каталогов. По умолчанию значение этого списка содержит каталог,
где хранится Лисп-код самого Emacs. Если у вас есть свои собственные
библиотеки, поместите их в один каталог и добавьте этот каталог к
load-path
. nil
в этом списке означает текущий каталог по
умолчанию, но скорее всего, ставить в список nil
-- не самая
лучшая идея. Если вы сами решили, что хотите иметь nil
в этом
списке, то наиболее вероятно, что в действительности вы хотите в этот
раз использовать M-x load-file.
Часто вы не должны давать никакой команды, чтобы загрузить
какую-нибудь библиотеку, так как определенные в ней команды настроены
таким образом, что выполняют автозагрузку этой библиотеки.
Попытка запуска любой из этих команд приводит к вызову load
для
загрузки нужной библиотеки. Это меняет определения автозагрузки на
действительные определения из библиотеки.
Код на Emacs Lisp может быть откомпилирован в байт-код, который
загружается быстрее, занимает после загрузки меньше памяти и быстрее
выполняется. Смотрите раздел `Byte Compilation' в the Emacs Lisp Reference Manual. По соглашению,
скомпилированный код библиотеки помещается в отдельный файл, чье имя
состоит из имени исходного файла библиотеки с добавленным `c'.
Таким образом, скомпилированный код для `foo.el' попадает в
`foo.elc'. Поэтому load-library
сначала ищет
`.elc'-файлы.
Программы на Лиспе, предназначенные для запуска в Emacs, нужно редактировать в режиме Emacs-Lisp. Это происходит автоматически для файлов, чьи имена кончаются на `.el'. В противоположность этому, сам режим Lisp используется для редактирования Лисп-программ, предназначенных для других Лисп-систем. Чтобы перейти в режим Emacs-Lisp, используете команду M-x emacs-lisp-mode.
Для проверки программ на Лиспе, предназначенных для запуска в Emacs, часто полезно вычислять какую-нибудь часть программы в том виде, как она находится в буфере Emacs. Например, после изменения текста определения лисповской функции, вычисление определения устанавливает это изменение для будущих вызовов функции. Вычисление лисповских выражений также удобно при любом редактировании для запуска неинтерактивных функций (функций, которые не являются командами).
eval-expression
).
eval-last-sexp
).
eval-defun
).
M-: (eval-expression
) -- это самая основная команда для
интерактивного вычисления лисповских выражений. Она считывает
выражение, используя минибуфер, так что вы можете выполнить любое
выражение в любом буфере, независимо от того, что этот буфер содержит.
Когда выражение вычислено, то текущим буфером опять является тот,
который был текущим, когда вы набирали M-:.
В режиме Emacs-Lisp ключ C-M-x привязан к команде
eval-defun
, которая анализирует определение функции, следующее за
точкой или содержащее ее, как выражение Лиспа и вычисляет его. Значение
печатается в эхо-области. Эта команда удобна для установки в среде
Лиспа изменений, которые вы только что сделали в тексте определения
функции.
C-M-x обрабатывает выражения defvar
особо. Обычно
вычисление выражения defvar
не делает ничего, если определяемая
им переменная уже имеет значение. Но C-M-x всегда
переустанавливает эту переменную в начальное значение, заданное
выражением defvar
. Эта особенность удобна для отладки программ
на Лиспе.
Команда C-x C-e (eval-last-sexp
) вычисляет лисповское
выражением, находящееся в этом буфере перед точкой, и показывает его
значение в эхо-области. Она доступна во всех основных режимах, а не
только в режиме Emacs-Lisp. Она не обрабатывает defvar
особо.
Если командам C-M-x, C-x C-e или M-: задан числовой аргумент, то они вставляют значение в текущий буфер в позиции точки, а не в печатают эхо-области. Значение аргумента не играет роли.
Самой общей командой для вычисления Лисп-выражений из буфера является
eval-region
. M-x eval-region анализирует текст из области
как одно или несколько лисповских выражений, вычисляя их одно за другим.
M-x eval-current-buffer похожа на предыдущую, но вычисляет весь
буфер. Это оправданный способ установки Лисп-кода из файла, который вы
как раз готовы проверить. После нахождения и исправления ошибки
используйте C-M-x в каждой функции, которую вы изменяете. Это
сохранит соответствие между миром Лиспа и исходным файлом.
Буфер `*scratch*', выбираемый в момент запуска Emacs, предназначен для интерактивного вычисления Лисп-выражений внутри Emacs.
Простейший способ использования буфера `*scratch*' -- вставлять лисповские выражения, оканчивая каждое из них вводом C-j. Эта команда считывает Лисп-выражение перед точкой, вычисляет его и вставляет его значение в печатном представлении перед точкой. Результатом будет полный протокол вычисленных вами выражений и их значений.
Основной режим буфера `*scratch*' называется Lisp Interaction; он во всем эквивалентен режиму Emacs-Lisp, за исключением привязки для C-j.
Целесообразность этого свойства состоит в том, что у Emacs должен быть буфер в момент запуска, но этот буфер неудобен для редактирования файлов, так как новый буфер создается для каждого файла, к которому вы обращаетесь. Я думаю, что самое полезное, что может делать начальный буфер, -- это вести протокол интерпретатора Лиспа. M-x lisp-interaction-mode переведет любой буфер в режим Lisp Interaction.
Альтернативный способ интерактивного вычисления выражений Emacs Lisp предоставляет режим Inferior Emacs-Lisp, который имеет интерфейс, похожий скорее на интерфейс режима Shell (смотрите раздел Режим Shell). Наберите M-x ielm, чтобы создать буфер `*ielm*', использующий этот режим.
Emacs имеет средства для запуска программ в других Лисп-системах. Вы можете запустить Лисп-процесс как подчиненный процесс Emacs и передавать ему выражения, которые нужно вычислить. Вы также можете передать подчиненному Лисп-процессу измененные определения функций непосредственно из буферов Emacs, в которых вы редактируете программы на Лиспе.
Чтобы запустить подчиненный Лисп-процесс, наберите M-x run-lisp.
Это запускает программу с именем lisp
, ту же программу,
которую бы вы запустили, набрав lisp
как команду оболочки, с
выводом и вводом, идущими через буфер Emacs с именем `*lisp*'.
Следует сказать, что любой "терминальный вывод" от Лиспа пойдет в этот
буфер, передвигая вперед точку, и любой "терминальный ввод" для Лиспа
приходит из текста в буфере. (Вы можете изменить имя исполняемого
файла Лиспа, установив переменную inferior-lisp-program
.)
Чтобы дать ввод в Лисп, отправьте сь в конец буфера и наберите нужный текст, завершив его вводом RET. Буфер `*lisp*' находится в режиме Inferior Lisp, режиме, который объединяет специальные характеристики режима Lisp и большую часть свойств режима Shell (смотрите раздел Режим Shell). Определение RET как команды, посылающей строку подпроцессу, -- это одна из особенностей режима Shell.
Для запуска исходных файлов программ во внешних Лиспах используйте режим Lisp. Этот режим можно выбирать при помощи M-x lisp-mode; он используется автоматически для файлов, имена которых оканчиваются на `.l', `.lsp' или `.lisp', какие и применяются в большинстве Лисп-систем.
Когда вы редактируете функцию в программе на Лиспе, которая работает в
данный момент, простейшим способом пересылки измененного определения в
подчиненный Лисп-процесс является ключ C-M-x. В режиме Lisp при
этом запускается функция lisp-send-defun
, которая находит
определение функции рядом или следом за точкой и посылает его как ввод в
Лисп-процесс. (Emacs может послать ввод в любой подчиненный процесс
независимо от того, какой буфер является текущим.)
Сравним значения C-M-x в режиме Lisp (для редактирования программ, запускаемых в другой Лисп-системе) и режиме Emacs-Lisp (для редактирования программ на Лиспе, предназначенных для работы в Emacs): в обоих режимах она имеет действие установки определения, в котором находится точка, но способ выполнения этого различается, согласно тому, где находится соответствующая среда Лиспа. Смотрите раздел Исполнение лисповских выражений.