Редактирование файлов в формате SGML с помощью текстового редактора Emacs
Инфосистемы Джет
2001
Emacs появился в 1976 году в виде набора "макросов", написанных Ричардом Мэтью Сталлманом для текстового редактора TECO миникомпьютера DEC PDP-10. За прошедшие годы Emacs сумел отделиться от TECO и стать полновесным редактором, чрезвычайно популярным среди пользователей. Это стало возможным по двум причинам: во-первых, свободно распространяемая версия Emacs доступна для всех желающих, во-вторых Emacs является полностью адаптируемым редактором.
Многие редакторы и текстовые процессоры претендуют на репутацию полностью адаптируемых. Допустим, что некий набор операций можно выполнить нажатием одной-двух клавиш или с помощью соответствующей команды меню. Возможно также, этот набор операций допускает использование циклов операторов и "умеет" реагировать на операторы "if", которые выполняют ту или иную группу действий, в зависимости от выполнения определенных условий. В таких случаях сторонники того или иного редактора заявляют, что этот редактор обладает способностью полноценного программирования. Обычно подобная характеристика является преувеличением, но только не для редактора Emacs.
Встроенный в Emacs язык программирования называется "Emacs LISP", потому что он базируется на давно существующем языке LISP. Чтобы использовать язык Emacs LISP, нет необходимости его изучать. Многие пользователи редактора Emacs сделали свои программы, написанные на языке Emacs LISP, доступными для всех желающих, независимо от степени понимания соответствующих программ.
Пакет подобных программ, имеющий название PSGML, позволяет читать и анализировать документы таким образом, что редактор Emacs можно использовать для работы с файлами, имеющими формат SGML. PSGML позволяет:
Так же, как и редактор Emacs, программный пакет PSGML распространяется свободно.
В данной главе объясняются основные принципы использования редактора Emacs, применяемые для работы с любым текстовым файлом. Затем описывается процесс инсталляции программного пакета PSGML и его использование для редактирования документов, созданных в формате SGML.
ПРИМЕЧАНИЕ:Поскольку редактор Emacs был создан довольно давно, то пользователь, привыкший к терминологии современного программного обеспечения, может не знать некоторых терминов, применяемых в этом редакторе. В этой главе разъясняются термины редактора Emacs и там, где это возможно, приводятся соответствующие термины, используемые в современных текстовых редакторах и процессорах. Такой подход облегчает работу со справочной информацией редактора Emacs и с другой доступной информацией об этом редакторе.
Emacs, по современным меркам, является очень старым продуктом. Его возраст и открытость кода привели к тому, что в настоящее время существует несколько независимых версий редактора. На данный момент стандартной считается версия Free Software Foundation's GNU Emacs. Другие версии редактора в большей или меньшей степени отличаются от стандартной, и поэтому с большой вероятностью расширения, предоставляемые пакетом PSGML, с ними работать не будут. Автор использовал версию GNU Emacs "EMX release 19.29.2" для DOS и "EMX release 19.30" для Windows 95. Также использовалась версия 1.0 alpha 6 PSGML.
Все версии редактора GNU Emacs, начиная с 19.19, а также все версии Xemacs, начиная с версии 19.9, будут работать с PSGML.
ПРИМЕЧАНИЕ:Стафлин (Staflin) сделал доступным использование PSGML под UNIX. Если у возникли проблемы с использованием новейшей версии PSGML в операционной системе - попробуйте другую версию PSGML. Было разработано несколько версий.
Редактор Emacs предоставляет пользователю возможность выбора между командой и комбинацией клавиш для выполнения той или иной операции. В данной главе описывается "минимальный набор" комбинаций, необходимых для работы.
Чтобы запустить редактор Emacs просто введите в командной строке
emacs |
После запуска редактора (без имени файла в качестве параметра) на экране отображается информация о версии Emacs (см. рис. Окно редактора Emacs.).
Нижняя строка, в которой написано "For informafion about..." (см. рис. Окно редактора Emacs.), называется окном "минибуфера" (minibuffer). Пользователь вводит в этом окне соответствующие команды, а редактор выводит в это окно различные сообщения. Например, сообщение о необходимости сохранения файла при выходе.
Прямо над окном минибуфера располагается "строка состояния" (mode line), в которой присутствует справочная информация: имя редактируемого файла (или буфера), информация об установках редактора и т.п.
В строке состояния, помимо прочего, указывается какой "расширенный" (major) режим задействован для данного буфера. Расширенный режим позволяет установить набор специфических команд для какого-либо типа файлов. Напротив, "обычный" (minor) режим использует вполне определенный набор установок.
Возможность настройки расширенного режима позволяет настроить Emacs для работы с текстами программ различных языков программирования. На самом деле, данное руководство посвящено описанию расширенного режима - режима работы с PSGML.
При запуске Emacs в качестве параметра можно указать имя файла. Для этого в командной строке нужно набрать:
emacs myfile.txt |
Что же такое буфер? Буфер - это область памяти, отводимая редактором под документ. При открытии редактор считывает содержимое файла и помещает его в память компьютера. Вот почему все несохраненные изменения будут утрачены при "зависании" компьютера или его выключении. Обычно буферы имеют те же имена, что и загруженные в них файлы.
Чтобы закончить сеанс работы с Emacs нажмите C-x C-c (Ctrl+c при нажатой Ctrl+x). Если версия Emacs имеет меню, то выберите пункт Exit Emacs в меню File. Если в файл не был изменен, то Emacs закроется и на экране появится командная строка (или просто закроется окно редактора). Если в файле имеются несохраненные изменения, Emacs выведет в окно минибуфера сообщение:
Save file c:/pathname/filename.ext? (y, n, !, ., q, C-r or C-h) |
Если на запрос был дан ответ n, то редактор даст еще один шанс сохранить изменения и выдаст сообщение:
Modified buffers exist; exit anyway? (yes or no) |
Некоторые версии Emacs предоставляют пользователю возможность через раскрывающиеся меню получить максимальный доступ к возможностям редактора. PSGML, в свою очередь, добавляет несколько новых окон к меню Emacs. Зачастую при вводе текста и перемещении по нему курсора использование меню требует большего времени, чем потребуется на нажатие соответствующей кнопки. Однако меню становятся полезными при работе с редкоиспользуемыми или труднозапоминаемыми комбинациями кнопок. Эта глава посвящена описанию использования пунктов меню, соответствующих определенным командам.
Обычно пользователь "говорит" редактору Emacs что именно нужно делать при нажатии специальных кнопок. Например, С-а (произносится "Control A" - нажатие клавиши А при нажатой клавише Ctrl) означает "переход курсора в начало текущей строки."
Многие команды Emacs выполняются при нажатии клавиши, называемой еще Meta-кнопкой. Некоторые ранние компьютеры имели специальную кнопку, которая именно так и называлась. Эта кнопка использовалась в комбинации с другими кнопками точно также, как в настоящее время используют клавишу Ctrl. На современных клавиатурах клавиша с названием "Meta" отсутствует. Вместо нее можно использовать Escape или Alt.
Комбинация с Meta-кнопкой предшествующая нажатию других клавиш обозначается через "М-". Например, M-f означает нажатие клавиши f при уже нажатой кнопке Escape. Если ваш компьютер или версия Emacs позволяет использовать кнопку Alt вместо метаклавиши, нажимайте ее в комбинации с другими клавишами точно так же, как это обычно делают с клавишами Ctrl или Shift.
Существуют команды, которые требуют нажатой клавиши Escape перед нажатием комбинации с кнопкой Ctrl. Такие комбинации обозначают M-C-x (Meta-Control-x). В документации также встречается обозначение ESC-C-x (если версия Emacs позволяет использовать Alt в качестве метаклавиши, то нужно нажать Alt+Ctrl+x). Данный документ описывает только один вариант использования метаклавиши.
Большое число команд Emacs выполняется при последовательном нажатии двух комбинаций клавиш. Например, нажатие С-x, а затем С-s (сокращенно пишется C-x C-s) приводит к записи текущего файла. Зачастую подобные комбинации группируются таким образом, чтобы по первой комбинации можно было определить к какому "семейству" относится команда. Например, все команды, начинающиеся с C-x - это команды работы с файлами: открытие, сохранение, выход без сохранения и т.п. Большинство этих команд представлены в пункте меню File.
Иногда первая комбинация клавиш вызывает на экран меню потенциально возможных вторых клавиш. Например, нажатие C-h приводит к появлению в окне минибуфера следующей строки:
C-h (Type ? for futher options) |
Возможности редактора Emacs настолько велики, что трудно предусмотреть такое большое число комбинаций клавиш для их реализации. Поэтому часто возникает необходимость вызвать командную строку, где вручную можно было бы набрать ту или иную команду. Нажатие M-x (x при нажатом Escape) делает доступным командную строку в окне минибуфера. При использовании дополнительных пакетов, таких как PSGML, расширяющих возможности Emacs, командная стока становится просто незаменимой.
Например, команда goto-line не имеет определенной комбинации клавиш (как это исправить будет показано в разделе "Настройка редактора Emacs"). Однако пользователь может заставить курсор перейти в указанную строку. Для этого нужно вызвать через M-x командную строку, набрать там команду goto-line и нажать Enter. Тогда Emacs выдаст в окне минибуфера подсказку:
Goto line: |
Прежде, чем приступать к исследованию возможностей многошаговых команд, нужно хорошо запомнить комбинацию клавиш, позволяющую прервать операцию - эта комбинация C-g. Например, при нажатии C-x Emacs выводит в окне минибуфера
C-x- |
Другой пример. К тяжелым, в плане понимания, последствиям приводит двойное нажатие клавиши Escape. В некоторых версиях UNIX последствия такого нажатия настолько необычны, что приводят пользователя в замешательство. В данном случае для отмены действия также нужно нажать C-g.
Большинство версий редактора Emacs поддерживают стандартные клавиши для перемещения курсора: up(стрелка вверх), down(стрелка вниз), left(стрелка влево), right(стрелка вправо);C-left и C-right для перемещения на целое слово влево или вправо; Page UP и Page Dоwn для перелистывания на одну страницу вперед или назад. Если возникают проблемы при использовании этих клавиш (например, если вы пользователь UNIX-машины и работаете через телефонную линию связи посредством телекоммуникационной программы, то клавиша Page Down запускает команду загрузки файла: "start downloading a file"), в этом случае можно использовать оригинальные команды редактора Emacs, доставшиеся в наследство от тех времен, когда клавиатуры не имели никаких специальных клавиш для перемещения курсора. Приводимый ниже список включает в себя комбинации клавиш и соответствующие им команды:
C-p | previous-line | перемещение на одну строку вверх |
C-n | next-line | перемещение на одну строку вниз |
C-b | backward-character | перемещение на один символ влево |
C-f | forward-character | перемещение на один символ вправо |
M-b | previous-word | перемещение на одно слово влево |
M-f | next-word | перемещение на одно слово вправо |
M-v | previous-page | перемещение на одну страницу назад |
C-v | next-page | перемещение на одну страницу вперед |
Следующие комбинации клавиш также способствуют ускоренному перемещению курсора по тексту:
C-a | beginning-of-line | перемещение курсора в начало строки |
C-e | end-of-line | перемещение курсора в конец строки |
M-< | beginning-of-buffer | перемещение в начало данного буфера |
M-> | end-of-buffer | перемещение в конец данного буфера |
Чтобы ввести текст, просто установите курсор в нужное место и начинайте печатать. Если создается новый документ, то курсор будет находится в начале.
Если при наборе текста вы дошли до конца строки и продолжаете печатать, то в конце строки появится знак перехода на следующую строку. В качестве такого знака перехода некоторые версии Emacs используют обратный слеш ("\"), но это может быть и какой-либо другой знак (например, стрелка).
Returning to the Spouter-Inn from the Chapel, I found Queequeg ther q\ uit alone; he having left the Chapel before the benediction some time. |
Конечно, можно каждый раз нажимать Enter, чтобы начать печатать с новой строки. Однако, многие текстовые процессоры автоматически вставляют символ перевода каретки при приближении редактируемой строки к правой границе. Для того, чтобы задействовать в Emacs аналогичную опцию нужно нажать M-x и набрать в командной строке auto-fill-mode. Данная команда включает режим "Fill", что отображается в строке состояния словом "Fill"(см. рис. Строка состояния Emacs.).
Если по каким-либо причинам, например при редактировании текстов программ, нужно отключить режим "Fill", повторите вышеописанную процедуру. Т.е. в командной строке (M-x) нужно набрать auto-fill-mode, которая работает в режиме переключателя: если "Fill" был включен, то команда auto-fill-mode его выключит, и наоборот.
Чтобы изменить положение правой границы (или, оперируя терминами Emacs, "fill column"), нажмите C-u, затем введите номер позиции, соответствующей новой ширине текста и нажмите C-x f.
Чтобы удалить символ в позиции курсора нажмите клавишу Delete. Это должно сработать, если нет, то используйте комбинацию C-d. Клавиша Backspace должна функционировать нормально.
ПРИМЕЧАНИЕ:При работе с UNIX-системой с PC через программу-эмулятор терминала клавиша Delete может работать не так, как ожидается. Например, при ее нажатии может удаляться символ слева от курсора. В этом случае использование комбинации C-d является вполне оправданным.
Чтобы удалить фрагмент от курсора до конца строки нажмите C-k (kill-line - неудачное название для команды, которая удаляет не всю строку, а только ее часть).
Другое замечательное свойство Emacs - это возможность переформатирования параграфа. Например, в приведенном ниже фрагменте была удалена часть текста в третьей строке, поэтому данная строка заполнена наполовину:
He made me a present of his embalmed head; took out his enormous tobacco wallet, and groping under the tobacco, drew out some thirty dollars in silver; then spreading them on the table, and mechanically dividing them into two equal portions, pushed one of them towards me, and said it was mine. |
He made me a present of his embalmed head; took out his enormous tobacco wallet, and groping under the tobacco, drew out some thirty dollars in silver; then spreading them on the table, and mechanically dividing them into two equal portions, pushed one of them towards me, and said it was mine. |
Рассмотренная выше ситуация типична при работе с текстовыми процессорами, но никак не для редакторов. Большинство редакторов были разработаны для программистов, оперирующих строками, а не параграфами. fill-paragraph обрабатывает фрагмент текста, заключенного между двумя пустыми строками. Если переформатированный фрагмент не удовлетворяет требованиям, действие можно отменить нажатием C-_ (команда UNDO).
Иногда удобно добавить в текст информацию из уже существующего файла. Чтобы это реализовать, поместите курсор в нужное место и нажмите C-x C-i. В окне минибуфера появится строка:
Insert file: c:\pathname\ |
Чтобы сохранить уже существующий файл, который был подвергнут редактированию просто нажмите C-x C-s (или выберите из меню Files пункт Save Buffer) для запуска команды save-buffer. Чтобы сохранить вновь созданный файл под новым именем, нажмите C-x C-w (или выберите из меню Files пункт Save Buffer As...) для запуска команды write-file. Emacs попросит ввести имя файла. При необходимости можно воспользоваться кнопкой Backspace, чтобы стереть предложенный путь и набрать новый:
Write file: c:\pathname\ |
Аналогично многим популярным текстовым процессорам и редакторам, Emacs позволяет вырезать, копировать и вставлять выделенные блоки текста. Корни этих операций для редактора Emacs уходят в бронзовый век компьютерной эры, поэтому описание команд могут показать современному пользователю несколько странными. Для избежания разночтений ниже приводится полезный словарик:
region | Блок текста |
point | Положение курсора |
mark | Если перед курсором - начало выделяемого блока, Если после курсора - конец выделяемого блока |
kill ring | Временная область памяти, куда помещается текст, который позднее будет скопирован или перемещен. В более поздних текстовых процессорах эту область часто называют "clipboard" или "буфером обмена". Хотя kill ring способен удерживать несколько блоков удаляемого или копируемого текста. |
kill-region | Операция по удалению выделенного блока и сохранению его содержимого во временном буфере в kill ringВ современных текстовых процессорах эта операция известна как удаление блока в "буфер обмена". |
copy-region | копирование выделенного блока в буфер обмена. |
yank | Вставка блока, помещенного последним в буфер обмена, в текущую позицию курсора. Современные текстовые процессоры, использующие терминологию "clipboard" (буфер обмена), называют эту операцию "Вставка" ("Paste"). |
В современных версиях Emacs в меню Edit, оперирующему вышеописанными объектами и операциями, все чаще используется современная терминология.
Любая операция копирования, перемещения или удаления начинается с выделения блока текста. Для того, чтобы начать выделение блока, поместите курсор в начало блока и нажмите C-spase (или C-@, обе эти комбинации соответствуют команде set-mark-command), перемещая курсор стандартными клавишами, установите его в конце блока. Операцию выделения можно выполнять в обратном порядке: нажать C-spase в конце блока, а затем установить курсор в начало.
Некоторые версии Emacs отображают цветом выделяемую область. Однако многие версии этого не делают, поэтому так легко забыть какой именно текст выделяется. Это может привести к неприятностям при использовании впоследствии команды delete. Чтобы исключить подобные ситуации, существует команда exchange-point-and-mark (C-x C-x), которая позволяет проверить установленные границы выделенного блока путем "перепрыгивания" курсора в начало/конец блока. Повторное нажатие комбинации C-x C-x возвращает курсор в прежнюю позицию.
Чтобы выполнить операцию удаления блока delete (или "kill"), нажмите C-w или выберите команду Cut из меню Edit. Если блок был удален случайно, операция отката (yank) удалит этот блок из буфера обмена (kill ring) и вернет его обратно нажатием клавиши C-y. Если перед операцией отката курсор был перемещен, то блок текста будет возвращен в текущую позицию курсора.
Наличие в меню Edit пункта Select and Paste(в Xemacs отсутствует - прим. перев.) расширяет возможности использования команды yank. Select and Paste выводит на экран каскадное меню, содержащее несколько последних скопированных в буфер блоков.
Можно скопировать блок в "kill ring", выбрав команду Copy из меню Edit или нажав M-w (команда kill-ring-save). Данная процедура никак не скажется на редактируемом файле, но сделает доступным многократное использование однажды скопированного в буфер блока.
В текстовых процессорах, использующих буфер обмена (clipboard), удаленный или скопированный в буфер текст замещает уже находящийся там текст. В таких редакторах если планируется что-либо удалить или скопировать, чтобы позднее вставить фрагмент, то операцию по перемещению выделенного блока в буфер нужно выполнять непосредственно перед вставкой текста. Команда yank-pop редактора Emacs позволяет копировать блоки текста независимо от того, когда он был помещен в буфер. Количество удерживаемых в буфере обмена блоков зависит от версии Emacs.
Пример. В нижеприведенном тексте требуется переместить строку со словом "red", поставив ее после строки со словом "blue".
yellow red black white blue green |
Переместите курсор в начало строки со словом "red" и нажмите C-space, чтобы обозначить начало выделяемого блока. Затем переместите курсор в начало следующей строки и нажмите C-w, чтобы удалить выделенную строку.
yellow black white blue green |
Пускай после удаления строки со словом "red", нужно удалить строку со словом "white". Воспользовавшись той же самой комбинацией клавиш, получим следующий список:
yellow black blue green |
Далее, для того, чтобы вставить строку со словом "red" перемещаем курсор в строку со словом "green", устанавливаем курсор на букве "g" (поскольку "red" должно быть вставлено перед "green"). Нажмите C-y, чтобы вставить удаленный текст в текущую позицию. И тут обнаруживается, что вместо слова "red" вставлено слово "white":
yellow black blue white green |
Здесь нет никакой ошибки. Просто запомните еще одну yank-pop команду, которая последовательно вставляет в текущую позицию блоки, помещенные в буфер kill ring. Нужно нажать M-y, и в строке появиться "red" вместо ранее вставленного "white":
yellow black blue red green |
Команда поиска в большинстве версий Emacs реализована в виде, так называемого, "инкрементного поиска" ("incremental search"). Нажмите C-s и введите образец для поиска в строку минибуфера "n". По мере ввода текста курсор будет перемещаться по тексту выделяя обнаруженные с образцом совпадения.
Пример. Пусть требуется найти слово "hazel" в приведенном ниже тексте. После того, как в окне минибуфера будет напечатана буква "h", курсор перепрыгнет в следующую позицию после первой обнаруженной буквы "h" (см. рис. Результаты инкрементного поиска после ввода первого символа.).
После того, как будет набрана следующая буква - "a", курсор перепрыгнет в "n" слова "than" - следующую позицию после обнаруженного образца "ha" (см. рис. Результаты инкрементного поиска после ввода второго символа.).
Напечатайте "z" и курсор перейдет в "e" после фрагмента "haz" в слове "hazel" (см. рис. Результаты инкрементного поиска после ввода третьего символа.).
Если Emacs не смог найти образец в тексте, то в окне минибуфера появится соответствующее сообщение. Например, если вместо "haz" набрать "hazx", то в окне минибуфера появится сообщение:
Failing I-search: hazx |
Если искомый фрагмент найден и нужно найти следующий, нажмите C-s еще раз. Чтобы остановить процесс поиска нажмите Enter.
Другая полезная клавиша при поиске - это клавиша Backspace. Ее используют, чтобы удалить последствия последней нажатой в окне минибуфера. Например, в рассмотренной выше ситуации если нажать Backspace после нажатия "z", когда Emacs нашел фрагмент "haz", курсор перепрыгнет обратно в слово "than", обнаруженное по фрагменту "ha".
Поиск по тексту в обратном направлении осуществляется точно также, как поиск в прямом направлении, с той лишь разницей, что для запуска команды поиска нужно нажать C-r. Точно так же поиск будет осуществляться в соответствии с вводимыми в образец буквами, пока либо Emacs не сможет найти образец в тексте, либо пользователь не прервет операцию поиска нажатием клавиши Enter. Точно также для поиска в обратном направлении работает клавиша Backspace.
В редакторе Emacs есть несколько команд осуществляющих операции замены (Search and Replace). Наиболее универсальная команда query-replace запускается при нажатии комбинации M-% или из пункта меню Query Replace... (меню Edit). При нажатии M-% в окне минибуфера появляется сообщение:
Query replace: |
Query replace my fault with: |
Query replacing my fault with your fault: (? for help) |
y | Заменить найденный фрагмент и искать следующий. Тот же эффект дает нажатие пробела. |
n | Замену не проводить, искать следующий. |
q | Замену не проводить. Прекратить операцию поиска. |
! | Заменить все обнаруженные в тексте фрагменты без дополнительного подтверждения. |
Комбинация C-x C-f запускает команду поиска файлов - find-file. Используя эту комбинацию (или выбирая Find File... меню File), пользователь как бы говорит редактору: "Открыть файл, имя которого будет задано, если он уже в буфере - показать этот буфер. Если файла с таким именем нет в буфере, но он есть на диске - сообщить, где именно он находится, чтобы можно было его открыть. Если такого файла вообще не существует - создать его." В окне минибуфера появится сообщение с предложением ввести имя текущей директории, где возможно находится файл:
Find file: c:\pathname\ |
Чтобы переключиться из одного активного буфера в другой, используйте комбинацию C-x b (команда switch-to-buffer). Emacs попросит ввести имя буфера, которое совпадает с именем редактируемого файла. При вводе имени буфера также можно пользоваться функцией "дописывания".
Все буферы используют один и тот же буфер обмена (kill ring). Например, чтобы переместить параграф из file1.txt в file2.txt, нужно выполнить следующие действия:
После завершения операции копирования, чтобы сохранить изменения, нажмите C-x C-s. Данную команду удобно использовать, если нужно сохранить изменения только в текущем буфере, а остальные файлы оставить без изменений. Затем можно выйти из Emacs без сохранения, воспользовавшись C-x C-c.
Когда Emacs ожидает ввода информации, и неясно, что нужно ввести, редактор может предложить возможные варианты.
Например, в предыдущем параграфе рассматривался пример с использованием C-x C-f, когда нужно было ввести имя файла. Пусть известна текущая директория, и пусть имя файла начинается с "apr". После того, как будет нажата комбинация C-x C-f и набрано "apr", нажмите клавишу Tab. Если хотя бы один из файлов начинается на указанную комбинацию, Emacs допишет столько символов, сколько будет возможно. Другими словами, если файл только один, то имя будет написано полностью. Если файлов несколько, то дописано будет до первой различной буквы в имени. Пусть в текущей директории существуют два файла april95.txt april96.txt, тогда Emacs после нажатия Tab добавит "il9". При этом экран будет разделен пополам, а в открывшейся половине будет приведен список файлов-вариантов (см. рис. Возможные варианты имен файлов.).
Теперь можно допечатать имя файла, а можно переместить курсор в новое окно, установить его на нужном файле и нажать клавишу ввода. В следующем параграфе будет показано как переходить из одного окна в другое, а также как закрыть ставшее ненужным окно.
Функцию дополнения имен используют не только для "дописывания" имен файлов, но и для "дописывания" длинных команд редактора в командной строке, таких как add-change-log-entry-other-window. "Дописывание" также полезно при работе с именами буферов.
Экран редактора Emacs может быть разделен на несколько частей, называемых окнами (не путать с окнами в многооконных системах), для одновременной работы с несколькими буферами. Время от времени Emacs сам открывает новые окна, чтобы отобразить соответствующую информацию (например, справочную информацию).
Нажатие C-x 2 (или выбор пункта Split Window из меню File) приводит к разделу экрана редактора пополам, т.е. на два окна. Оба окна отображают информацию из одного и того же буфера, текущего на момент раздела. Чтобы загрузить в разные окна разные файлы нужно выполнить следующее:
Переход из одного окна в другое осуществляется нажатием комбинации C-x o ("o" - буква, не цифра).
Удаление окна, в котором находится курсор, осуществляется комбинацией C-x 0 ("0" - цифра, не буква) или командой delete-window.
Комбинация C-x 1 запускает команду delete-other-windows, которая закрывает все окна, кроме текущего. Закрытие окна не означает закрытие буфера. Все буферы остаются доступными для редактирования, в любой из буферов можно переключится нажатием C-x b.
Чтобы вывести список доступных для редактирования буферов и переключиться в один из них, используется похожая комбинация клавиш: C-x С-b (list-buffers). Чтобы переключиться в один из отображенных в списке буферов, нажмите C-x о. Затем переместите курсор в строку с указанием имени буфера и нажмите 1. Буфер с выбранным именем отобразится во вновь открытом окне.
Вышеописанные операции с буферами также доступны из меню Buffers.
Emacs обладает весьма гибким окружением, которое может быть легко приспособлено для выполнения конкретных задач. Например, Emacs позволяет запоминать последовательности комбинаций клавиш, чтобы не нажимать много раз подряд одни и те же кнопки. Emacs позволяет также изменять окружение через написание процедур на языке программирование Emacs LISP. Описанию данных возможностей посвящена эта глава.
Emacs может запоминать, а затем воспроизводить, последовательности комбинаций клавиш. Начало и конец записи осуществляется нажатием комбинации C-x, а далее должна следовать одна из круглых скобок. Комбинация C-x ( запускает команду start-kbd-macro - начало записи макроса, а заканчивает запись комбинация C-x ) (end-kbd-macro) - конец записи.
Комбинация C-x e запускает команду call-last-kbd-macro. Данная команда запускает последний записанный макрос.
Если нужно создать несколько макросов, то создаваемым макросам нужно присвоить имена. Для этого из командной строки в окне минибуфера (комбинация M-x) запускается команда name-last-kbd-macro. После нажатия ввода, редактор предложит ввести имя макроса. Допустим это имя - testmacro, тогда из командной строки (комбинация M-x) для запуска данного макроса нужно будет набрать testmacro и нажать ввод.
При выходе из Emacs большинство макросов (именованных и нет), определенных в данной сессии, будут утрачены. Как этого избежать будет показано в конце главы.
Более серьезные настройки в редакторе Emacs осуществляются через написание процедур на языке LISP. Например, чтобы присвоить какой-либо клавише выполнение определенной команды, нужно вставить в конфигурационный файл строку, написанную на LISPе.
В языке программирования LISP, также как и в C, все определяется через функции. Можно использовать свои собственные функции, или библиотеки функций, написанных другими пользователями, - пакеты, чтобы настроить работу Emacs. PSGML - пакет, разработанный на LISPе. Однако, прежде, чем устанавливать PSGML, разберемся с более простыми случаями установки LISP-функций.
Все LISP-функции запускаются из файла .emacs.
ПРИМЕЧАНИЕ: Поскольку DOS не поддерживает длинные имена файлов, то версии Emacs под DOS и 16-bit MS Windows используют для автоматического запуска функций файл с именем _emacs.
Поначалу синтаксис новых функций, помещаемых в файл .emacs можно копировать у уже существующих функций, заменяя нужные места в названиях и командах. Поясним это на примере. Команда goto-line вызывается при нажатии комбинации M-g. Соответствующая функция в файле .emacs выглядит следующим образом:
(global-set-key "\eg" 'goto-line) ; M-g prompts for line number to enter |
Обычно команда goto-line не имеет комбинации клавиш, поэтому в таком редакторе нужно сначала нажать M-x, а затем из командной строки запустить команду goto-line. У программистов и пользователей SGML часто возникает необходимость перейти в строку с определенным номером, поэтому целесообразно вместо команды использовать комбинацию клавиш.
Если комбинация M-g не определена, то добавьте приведенную выше строку в файл .emacs, сохраните файл и перезапустите Emacs. Теперь при нажатии M-g в окне минибуфера появится сообщение:
Goto line: |
Другая популярная команда многих текстовых процессоров - overwrite-mode, которая переключает режим ввода текста между insert (Вставка) и replace (Забой). Пользователь, работающий с текстом скорее всего предпочтет работать в режиме вставки, чем каждый раз для перевода в режим Забоя вводить четырнадцатибуквенную команду. Целесообразно отредактировать файл .emacs, добавив в него строку, присваивающую комбинации M-i выполнение команды overwrite-mode. Воспользуемся в качестве заготовки строкой, определяющей комбинацию M-g.
Команда LISP, которая присваивает комбинации клавиш некую функцию Emacs - global-set-key. Эта команда имеет два параметра: комбинацию клавиш и присваиваемую ей команду. Клавиша Escape обозначается через "\e". Таким образом, комбинация M-i будет выглядит в LISPe "\ei". Следует помнить, также, что перед присваиваемой командой должна стоять одиночная кавычка "'" (это означает в LISP, что присваиваемая команда - символьное выражение). И последнее, символом комментария в LISP является ";", игнорируется все, что идет после этого знака.
Итак, строка в файле .emacs, которая присваивает комбинации клавиш M-i выполнение команды overwrite-mode выглядит следующим образом:
(global-set-key "\ei" 'overwrite-mode) ; toggle overwrite mode |
Другой пример. Применение описанной выше команды по отношению к клавише Ctrl. Присвоим комбинации С-t команду kill-word (в стандартном Emacs данная команда соответствует комбинации M-d). Запись в файле .emacs будет выглядеть следующим образом:
(global-set-key "^T" 'kill-word) ; enter ^T here with C-q C-t |
Другая частая причина редактирования файла .emacs заключается в изменении значений переменных. Процедуры Emacs используют в процессе работы переменные. Поэтому, изменяя значения встроенных переменных, можно влиять на поведение Emacs.
Некоторые переменные содержат числовые значения. Например, переменная next-screen-context-lines содержит количество строк данного экрана, остающихся при нажатии клавиш Page Up или Page Down. Если значение данной переменной - 2, то при нажатии одной из этих клавиш на экране останутся две строки от предыдущего экрана. Чтобы проверить значение данной переменной, введите C-h v, а затем имя переменной.
Значение переменных можно менять, если нажать M-x, а затем в командной строке ввести set-variable. Нажмите Enter, и Emacs запросит имя устанавливаемой переменной. После ввода имени Emacs запросит новое значение переменной.
Это - достаточно многоходовая комбинация, особенно если учесть имя переменной next-screen-context-lines. Если при каждом входе в Emacs, нужно устанавливать значение данной переменной равное 1, воспользуйтесь функцией Emacs LISP setq, чтобы автоматизировать данный процесс. Добавьте следующую строку в файл .emacs:
(setq next-screen-context-lines 1) |
Не все переменные поддерживают числовые значения. Некоторые, такие как load-path, являются символьными переменными. load-path - список подкаталогов, куда обращается Emacs, когда необходимо загрузить файл, содержащий LISP-программу. Как будет показано в главе "Редактирование Документов SGML в редакторе Emacs и PSGML", при работе с PSGML нужно будет изменить значение переменной load-path.
Многие переменные Emacs являются Булевыми. Булева переменная (названная по имени английского математика Джорджа Була, жившего в 19-м веке) - подобна выключателю, который может иметь только два положения: вкл. или выкл. Emacs использует большое количество Булевых переменных, что дает возможность гибкой настройки его работы. Например, можно задать, чтобы при пошаговом поиске (C-s или C-r) Emacs осуществлял поиск либо с учетом, либо без учета регистра.
Управлять чувствительностью к регистру можно меняя значение переменной case-fold-search. Чтобы заставить Emacs игнорировать значение регистра при поиске, добавьте следующую строку в файл .emacs:
(setq case-fold-search t) |
И наоборот, чтобы задействовать чувствительность к регистру в процессе поиска, установите переменной значение выкл.:
(setq case-fold-search nil) |
В других языках программирования Булевым переменным в значениях "вкл." и "выкл.", часто соответствуют значения переменных "true" и "false" или "1" и "0". Emacs, в соответствии с традициями LISP, использует для тех же целей "t" и "nil". Причем значение "t" ("истина"), является просто соглашением: все, что не "nil" ("ложь"), то "t"("истина"). Об этом нужно помнить при чтении документации по Emacs, в которой редко рекомендуется устанавливать значение переменной равной "t". Чаще можно встретить рекомендацию установить переменной значение "non-nil" ("t") для одного случая и значение "nil" для другого.
Чтобы сохранить клавиатурные макросы в файле ".emacs" так, чтобы можно было использовать макрокоманду без дополнительного переопределения, используется команда insert-kbd-macro, которая добавляет эквивалент макроопределения, написанный на Emacs LISP, в текущий буфер. Рассмотрим пример.
Удобная макрокоманда для пользователей SGML быстрый ввод комментариев. Чтобы определить макрос и начать запись макрокоманды, сначала нажмите C-x (, а затем наберите
<!-- --> |
Чтобы присвоить записанной макрокоманде имя, нажмите M-x и наберите в командной строке минибуфера name-last-kbd-macro. Допустим это имя - sgml-comment.
Затем, отредактируйте файл .emacs, или его эквивалент в операционной системе. Вставьте пустую строку, куда позднее будет вставлено макроопределение. Нажмите M-x, а затем в командной строке минибуфера введите команду insert-kbd-macro. Emacs запросит имя вставляемой макрокоманды, наберите sgml-comment. Появится следующее:
(fset 'sgml-comment [?< ?! ?- ?- ? ? ?- ?- ?> left left left left]) |
Теперь в среде Emacs появилась новая команда sgml-comment. Установите новой команде комбинацию клавиш C-c о. Для этого в файл .emacs добавьте строку
(global-set-key "^Co" 'sgml-comment) |
Emacs предлагает пользователю богатые возможности встроенной подсказки (On-line Help). Чтобы вызвать подсказку нужно нажать C-h. В окне минибуфера появится сообщение:
C-h (Type ? for further options)- |
Emacs предлагает так много разделов справки, что пользователь должен сообщить, какого рода справочная информация его интересует. Если ввести вопросительный знак, то Emacs разобьет экран и в отдельном окне покажет описание различных видов доступной справочной информации (см. рис. Виды доступной справочной информации Emacs.).
C-h a (command-apropos) |
C-h k (describe-key) |
C-h t (help-with-tutorial) |
C-h v (describe-variable) |
C-h i (info) |
Если версия Emacs не может найти файлы справки, добавьте следующую строку в файл .emacs, содержащую соответствующий путь (например, /pathname/emacs/info:
(setq Info-directory-list (cons "/pathname/emacs/info" Info-default-directory-list)) |
Ввод вопросительного знака после C-h равносилен запросу информации о самой системе справки. После того, как на экран будет выведена информация относительно встроенной подсказки, Emacs все еще будет ожидать ввода одного из ключей (кроме ?), который должен следовать непосредственно за C-h. Таким ключом для команды command-apropos был символ a, а для команды info - i.
Редактор Emacs фактически имеет встроенный режим для редактирования документов SGML, но это просто автоматизированная вставка разделителей - тэгов ("<" и ">") - и запрос внешней программы, который может проверять синтаксис файла типа nsgmls или sgmls.
PSGML - добавочный режим SGML для Emacs, расширяющий возможности SGML. PSGML расширяют возможности редактора Emacs. Данный режим позволяет редактировать документ, не волнуясь о его структуре, поскольку большинство задач, поддерживающих структуру документа, автоматизировано. Режим PSGML обеспечивает вставку соответствующих тэгов нажатием минимального числа клавиш или даже автоматически. Данный режим позволяет обнаруживать структурные ошибки, выравнивать тэги, обозначивая вложенные структуры. Допускается выделение тэгов, комментариев и ссылок на объекты различным шрифтом или цветом, чтобы облегчить визуальное восприятие структуры.
Пользователь обычно получает PSGML как совокупность файлов, объединенных в один сжатый файл типа DOS/Windows ZIP или UNIX GNU zip. Файлы, извлеченные из этого дистрибутивного файла относятся к трем главным категориям:
Пользователи UNIX обнаружат инсталляционные команды и сценарии, включенные в комплект поставки PSGML. Пользователям DOS/Windows придется выполнить важные шаги вручную.
Файлы .elc созданные для какой-либо конкретной версии Emacs или в специфической операционной системе скорее всего не будут работать с другой версией программы или на другой операционной системе. Но файлы .elc всегда можно создать самостоятельно из файлов .el. PSGML может работать и .el-файлами, но это несколько замедлит работу, поскольку перед каждым выполнением такого файла будет проходить процесс его компиляции.
Сначала, поместите все файлы из пакета PSGML в их собственный подкаталог и удостоверьтесь, что Emacs осведомлен об их местоположении. Для этого добавьте следующий LISP-код в файл .emacs:
(setq load-path (append (list nil "/app/emacs/psgml") ; substitute your PSGML directory name load-path)) |
ПРИМЕЧАНИЕ:Даже при использовании Emacs и PSGML под DOS/Windows, PSGML ожидает, что в имени каталога будет присутствовать прямой слеш ("/"), а не обратный ("\"), как это имеет место в упомянутых операционных системах.
Тем самым переменной Emacs load-path, содержащей имена каталогов, откуда происходит загрузка программ, будет добавлено имя каталога, содержащего файлы PSGML. Переместите файлы PSGML в каталог /app/emacs/psgml.
Затем, нажмите M-x и в командной строке наберите byte-compile-file. Нажмите ввод, и после Byte compile file: введите имя .el-файла. Снова нажмите ввод.
Повторите процедуру для всех файлов с расширением .el. Если в процессе трансляции появляются сообщения об ошибках, компилируйте другие файлы, а затем вернитесь к тем файлам, где были ошибки и попробуйте снова. Возможно, ошибки - это результат наложения от других файлов.
Ускорить процесс компиляции можно, если вместо команды byte-compile-file использовать команду byte-force-recompile, которая запрашивает имя каталога, а затем компилирует все .el-файлы из этого каталога.
Выше было упомянуто, что Emacs имеет встроенный режим SGML, который, однако, имеет ограниченный набор возможностей, поэтому следующим шагом нужно сообщить Emacs использовать PSGML вместо встроенного режима SGML. Сделать это можно добавлением строки
(autoload sgml-mode "psgml" "Major mode to edit SGML files." t ) |
Помимо программных файлов пакет PSGML включает в себя документацию, которую можно просматривать в Emacs средствами справки. Поместите файл psgml.info в каталог (вероятно, подкаталог главного каталога Emacs называемого info), где лежат все файлы подсказки. Отредактируйте файл dir, находящийся в том же каталоге, включив в него следующую строку:
* PSGML: (psgml). SGML editing. |
Если используется многопользовательская система, то возможно потребуется вмешательство системного администратора, чтобы добавить или отредактировать файлы из подкаталога каталога Emacs. Однако можно просматривать информацию, содержащуюся в файле psgml.info, в Emacs, поместив его другой каталог, куда есть доступ. Для этого введите команду
C-h i g (/pathname/psgml.info) |
ПРИМЕЧАНИЕ: Не забудьте убрать букву "o" в
расширении файла, если используется Emacs и PSGML под DOS, где
расширения файла могут содержать не более трех
символов.
При определении местоположения файла
информации учтите, что DOS/Windows Emacs допускает в
названиях каталогов как прямых слешей ("/"), так и
обратных ("\")
Каким образом Emacs узнает о необходимости загрузки режима PSGML? Это может быть осуществлено тремя способами:
<!-- -*- sgml -*- --> |
При запуске Emacs с PSGML и загрузке документа, PSGML не станет анализировать документ (если переменным sgml-auto-activate-dtd и sgml-set-face заранее не присвоены значения "t") пока не будет выполнена одна из команд определенной категории. Из-за этого, в частности, нельзя выполнять автоматическое форматирование текста, которое облегчает визуальное восприятие текста при редактировании документа. Например, не происходит выравнивание уровней вложенности элементов или отсутствует отображение разметки различными шрифтами или цветом. Одна из команд, которая способна заставить работать PSGML, это команда sgml-next-trouble-spot, которая может быть вызвана нажатием C-c C-o или через пункт Next Trouble Spot меню Move. В настоящее время PSGML еще не является полноценным синтаксическим анализатором (недостатки, как будет показано в главе "Обнаружение ошибок разметки", достаточно легко устранимы). PSGML может выявить достаточно большое количество потенциальных ошибок через синтаксический анализ, в то время, как часть из них может быть обнаружена еще на стадии визуального форматирования.
Наиболее часто встречающаяся проблема, с которой сталкивается команда sgml-next-trouble-spot связана с тэгами. Это может быть неизвестный вид тэга, или неверное расположение тэга в тексте, или непарные скобки тэга. Если ошибок не обнаружено, то курсор перемещается в конец документа, заканчивает визуальное форматирование, и отображает в окне минибуфера сообщение Ok.
С большим числом элементов DTD, подобный синтаксический анализ может потребовать времени. При этом в окне минибуфера будут отображаться сообщения типа "Parsing doctype" и "Garbage collecting" (сочный термин для процедуры реорганизации оперативной памяти). Ускорить данный процесс можно, если предварительно сохранить DTD в виде специальной откомпилированной версии, которую PSGML загружает гораздо быстрее. Данная процедура осуществляется запуском команды sgml-save-dtd из командной строки минибуфера M-x. PSGML предложит сохранить откомпилированную версию текста в том же самом каталоге с тем же самым именем, что и у редактируемого документа, но с расширением .ced. Если название каталога или имя файла будет изменено, то затем, при запуске команды sgml-load-dtd, нужно будет вводить полное имя пути откомпилированного файла. Если PSGML сохранят откомпилированный файл с заданным по умолчанию именем и каталогом, то при последующем редактировании этого документа, он будет сам находить эту откомпилированную версию.
PSGML не требует, обязательного включения в документ объявления SGML. Даже если такое SGML-объявление будет включено, PSGML проигнорирует его. PSGML использует Reference Concrete Syntax, но не поддерживает ограничения, накладываемые этим документом, на длину имени типа элемента.
PSGML должен знать, где обнаружить описания элементов DTD. Сообщить PSGML о местоположении описания элементов DTD можно тремя способами:
Первые два метода являются стандартными, и поэтому могут использоваться другими приложениями SGML. По этой причине, новичку лучше воздержаться от использования третьего метода.
Идентификатор SYSTEM - самый простой метод. Он вставляется в DOCTYPE определение, подобное приведенному ниже
<!DOCTYPE chapter SYSTEM "mybook.dtd"> |
<!DOCTYPE chapter system "\dev\sgml\dtds\mybook.dtd"> |
Некоторое программное обеспечение SGML более придирчиво относится к имени пути, ожидая встретить в имени пути прямые слеши "/", характерные для UNIX, вместо обратных "\", даже если используется система DOS или Windows. У PSGML не возникает никаких проблем со стилем DOS.
Идентификатор PUBLIC популярен при использовании известных элементов DTD. Объявление DOCTYPE включает строку после слова PUBLIC, как, например, в случае с DocBook DTD:
<!DOCTYPE chapter PUBLIC "-//Davenport//DTD DocBook V3.0//EN"> |
Тем не менее приложение SGML (в данном случае PSGML) все же должно знать, где лежит копия этого "общественного" DTD. Наиболее общий способ сообщить приложению данную информацию - через файл каталога в формате, определенном SGML Open Technical Resolution 9401:1995. Каждый вход этого файла (обычно называемый каталогом(catalog)), начинающийся с ключевого слова PUBLIC, идентифицирует DTD и фактическое имя файла системной копии DTD, а, в случае необходимости, его местоположение. Ниже приводятся примеры входов для DocBook и DTD HTML:
PUBLIC "-//Davenport//DTD DocBook V3.0//EN" "DOCBOOK.DTD" PUBLIC "-//IETF//DTD HTML//EN" "\WEBSTUFF\HTML.DTD" |
Обратите внимание, что вход DocBook не содержит никакого имени пути, указывая тем самым, что файл docbook.dtd находится в том же самом каталоге, что и файл catalog, в то время как вход HTML включает полное имя файла.
Таким образом, необходимо указать SGML и всем его приложениям местоположение файла catalog, чтобы они имели возможность использовать элементы DTD через объявления PUBLIC. Чтобы сообщить PSGML местоположение этого файла, нужно присвоить переменной SGML_CATALOG_FILES значение, содержащее полное имя файла catalog. Если файл имеет имя catalog и расположен в директории \dev\sgml\dtds\ (в синтаксисе DOS/Windows), то следующая команда сообщит PSGML, где найти файл catalog:
set SGML_CATALOG_FILES=\dev\sgml\dtds\catalog |
ПРИМЕЧАНИЕ: При установке окружения переменной синтаксис UNIX зависит от используемой оболочки shell.
Учтите, что элемент DTD может содержать объявления для установок объекта (ENTITY), которые он сам же использует, и что нужно сообщить приложениям, где найти эти установки объекта. Например, элемент DTD включает следующее объявление объекта, чтобы позволить использование в документах набора символов ISO:
<!ENTITY % ISOchars PUBLIC "-//ENTITIES Public ISO Character Entity Declarations//EN" "iso-public"> |
PUBLIC "-//ENTITIES Public ISO Character Entity Declarations//EN" "ISOPUB.ENT" |
PSGML облегчает возможность редактирования файлов SGML, добавляя команды для работы с фрагментами документа SGML, а также обеспечивая возможность вызова большинства этих команд через нажатие комбинации клавиш и пункты меню. Даже если версия Emacs или операционной системы, не поддерживает различные экранные шрифты, выделение цветом, или меню, к услугам пользователя PSGML еще остается встроенная интеллектуальная подсказка. PSGML читает и анализирует структуру документа, принимая на себя основные заботы по разметке текста и поддержке элементов DTD, помогая тем самым пользователю сосредоточится на содержании.
В разделе "Настройка переменных редактора Emacs" говорилось, что в Emacs существуют переменные, изменяя значения которых можно менять настройки редактора, и что эти переменные сохраняются в файле .emacs. PSGML добавляет к списку переменных несколько новых. Наиболее важные приведены ниже. Все они являются Булевыми переменными и должны иметь значение "t". Это можно сделать добавлением строки в файл .emacs, подобной той, что приведена ниже
(setq sgml-omittag-transparent t) |
При вставке нового элемента можно "попросить" PSGML перечислить все допустимые типы элемента, которые можно вставить в текущую позицию курсора. Если переменной sgml-omittag-transparent присвоено значение "nil" (ноль), PSGML только перечислит типы элемента, которые могут находиться внутри текущего элемента. Если переменной присвоено ненулевое значение - "non-nil", PSGML также перечислит доступные типы элементов, которые могут следовать за текущим элементом (то есть элементом, в котором расположен курсор), если текущий элемент элемент не нуждается в закрывающем тэге.
Например, если текущий элемент - элемент параграфа <para>, и DTD не требует, чтобы элементы параграфа имели закрывающий тэг, то при перечислении допустимых для вставки типов элементов, будут перечислены как те элементы, которые могут следовать непосредственно за элементом параграфа, так и те, которые могут находиться только внутри него.
Если этой переменной присвоено ненулевое значение, то каждый раз при вставке элемента PSGML будет вставлять элемент с открывающим и закрывающим тэгами, а курсор будет находиться между ними.
Если этой переменной присвоено ненулевое значение, то каждый раз PSGML будет вставлять какой-либо элемент вместе с тэгами любых требуемых элементов внутри этого элемента. Например, при использовании DocBook DTD, требование к PSGML вставить элемент главы chapter влечет за собой вставку тэгов элемента заголовка title в начале главы. При этом выводится комментарий о необходимости вставки одного из (далее следует список допустимых элементов).
Если этой переменной присвоено ненулевое значение, то PSGML будет выделять (если, конечно, это возможно на вашем мониторе) тэги, содержание, определения объектов и комментарии различным шрифтом или цветом. Подробнее см. раздел "Выделение Разметки шрифтом и цветом."
Если этой переменной присвоено ненулевое значение, то PSGML будет отображать тип документа и тип текущего элемента в строке состояния. Например, при использовании DocBook DTD, если курсор находится внутри элемента заголовка (title) при редактировании главы (chapter) документа, то в строке состояния возможно появление следующего сообщения:
(SGML [chapter/title])) |
Данная переменная "заставляет" PSGML автоматически выравнивать тэги в соответствии с установками относительно структуры элемента. Значение переменной sgml-indent-step по умолчанию равно двум, т.е. тэги вложенных элементов смещены друг относительно друга на два пробела вправо. Ниже будет показано, что элементы title, para, figure выровнены еще два символа относительно открывающих и закрывающих элементов sect2, также как и элементы title и graphic, помещенные внутрь элемента figure.
<sect2> <title>A Bosom Friend</title> <para>We then turned over the book together, and I endeavored to explain to him the purpose of the printing, and the meaning of the few pictures that were in it.</para> <figure> <title>A Sample Figure</title> <graphic fileref="giftest.gif" format="gif"></graphic> </figure> <para>Thus I soon engaged his interest; and from that we went to jabbering the best we could about the various outer sights to be seen in this famous town.</para> <sect2> |
(setq sgml-indent-step 0) ; default value is 2 |
Как и любые другие команды Emacs, команды PSGML могут быть запущены из командной строки (через нажатие M-x), через нажатие комбинации клавиш или из меню, если, конечно, используемая версия редактора поддерживает меню.
Комбинации клавиш, как правило, предоставляют самый быстрый способ запуска. Большинство комбинаций клавиш в SGML имеют вид, аналогичный соответствующим комбинациям, выполняющим в режиме простого редактирования похожие функции. Например, в обычном Emacs, M-f перемещает курсор на слово вперед, а M-b перемещает курсор на слово назад. В главе "Перемещение курсора в режиме SGML" будет показано, что комбинации клавиш C-M-f и C-M-b перемещают курсор на элемент вперед и назад соответственно (если, конечно, подобные комбинации клавиш реализованы в используемой версии Emacs). Напомним, что некоторые версии Emacs допускают нажатие клавиши Alt вместо Escape для имитации метаклавиши.
PSGML добавляет в Emacs шесть новых меню: SGML, Modify, Move, Markup, View, DTD. Ниже будет показано, что большинство пунктов меню имеют альтернативный вызов через комбинации клавиш.
Команда sgml-insert-element - одна из наиболее часто используемых команд при работе с PSGML. При вводе этой команды из командной строки (или при выборе пункта меню Insert Element из меню Markup, или при нажатии комбинации C-c C-e), PSGML попросит ввести имя элемента в строке минибуфера:
Element: |
Как обычно, при вводе команд в окне минибуфера можно использовать функцию дополнения имен команд. Для этого нужно набрать несколько первых символов команды и нажать клавишу Tab или пробел. Если несколько команд начинаются с введенной последовательности символов, то Emacs выведет в новом окне список возможных команд. Из которых нужно выбрать одну.
После ввода имени вставляемого элемента, PSGML вставит открывающий и закрывающий тэги, а также, если это необходимо, вложенные элементы. Для реализации данной функции необходимо, чтобы переменным sgml-balanced-tag-edit и sgml-insert-required-elements присвоены ненулевые значения (подробнее см. "Установка значений переменных PSGML"). Если нужно выбрать вставляемый элемент из нескольких аналогичных, PSGML вставит соответствующий SGML-комментарий. И последнее, PSGML установит курсор в конце отрывающего тэга, чтобы можно было сразу начать ввод информации.
Пример. Допустим, нужно вставить рисунок в документ DocBook. Нажмите C-c C-e, В окне минибуфера появится подсказка
Element: |
<figure> <title></title> <!-- one of (blockquote informalequation informaltable literallayout pr\ ogramlisting screen screenshot graphic synopsis cmdsynopsis funcsynopsis link o\ link ulink) --> </figure> |
Обратите внимание, как именно выглядит строка комментариев, вставленная после тэгов заголовка и сообщающая о необходимости вставки одного из перечисленных элементов. Комментарий получился слишком длинным и не уместился целиком на одной строке, поэтому он разбит на несколько кусков, в конце которых стоят символы переноса - обратный слеш "\". Это чисто технический перенос, необходимый для облегчения визуального восприятия. Чтобы убедиться, что это одна строка, поместите курсор в начале комментария и нажмите C-k (команда kill-line).
Данное описание может создать впечатление, что процедура вставки элемента рисунка, <figure>, - это довольно сложный процесс. Давайте посмотрим, как все выглядит в действительности:
Иногда нельзя сразу же начать печатать текст, поскольку модель вставленного элемента предусматривает наличие в этом месте подэлементов.
Рассмотрим пример. Добавим элемент DocBook ItemizedList (маркированный список). Для этого нажмите C-c C-e, наберите "it", а затем нажав Tab и Enter. Emacs "допишет" оставшуюся часть названия типа элемента. PSGML вставит тэги, обозначающие список, а также тэги элемента ListItem - первый элемент данного списка. Однако элемент ListItem может содержать такое большое количество элементов, что PSGML вставляет 400-символьный комментарий, чтобы сообщить о возможном выборе:
<ItemizedList> <ListItem> <!-- one of (sidebar procedure msgset simpara para formalpara funcsynop\ sis cmdsynopsis synopsis graphic screenshot screen programlisting literallayout\ informaltable informalequation blockquote variablelist simplelist segmentedlis\ t orderedlist ItemizedList indexterm highlights table figure example equation e\ pigraph comment bridgehead warning tip note important caution authorblurb ancho\ r abstract) --> </ListItem> </ItemizedList> |
При вводе простого текста часто требуется ввести элемент параграфа.
Если параграф не единственный допустимый тип элемента, начинающийся с символа "p", то, очевидно, потребуется ввести по крайней мере "pa" в поле Element: в окне минибуфера. Затем нужно нажать Tab, чтобы Emacs дополнил остальную часть названия типа элемента. Поскольку рассматриваемый тип элемента, параграф, возможно один из наиболее часто используемых, нужно учитывать, что комбинация клавиш, соответствующая команде PSGML sgml-split-element позволит произвести процедуру вставки элемента за меньшее число нажатий клавиши, чем C-c C-e метод.
Команда PSGML Sgml-split-element, вызываемая через C-c Enter, разбивает текущий элемент на два в позиции курсора. Если нужно, чтобы существующий параграф был разбит на два параграфа, нажмите указанную выше комбинацию клавиш, и Emacs вставит конечный и начальный тэги, соответствующие типу разбиваемого элемента. При этом курсор будет установлен после начального тэга нового элемента.
Помните, что команда Sgml-split-element автоматически не вставляет другие элементы, более высокого уровня вложения. Для проверки используйте команду sgml-next-trouble-spot или соответствующую комбинацию C-c C-o.
Еще одна полезная функция команды Sgml-split-element - возможность разделения структуры более высокого уровня. Так, если при нажатии C-c Enter был разделен элемент sect2, то в окне минибуфера появится следующее сообщение:
Repeat the command to split the containing sect1 element |
Можно использовать комбинацию клавиш M-q (команда fill-paragraph), чтобы корректировать концы строки, но далее, в разделе "Выравнивание текста элемента", будет показан более продуктивный путь.
При вводе нового текста удобно вставлять пару элементов, начальный и конечный тэги, а курсор помещать между ними. Ниже будет рассмотрено, каким образом можно внести разметку в уже существующий текст. Для этой цели предусмотрены команды sgml-tag-region, sgml-insert-tag и sgml-insert-end-tag, а также соответствующие комбинации клавиш.
Нажмите C-c C-r (команда Sgml-tag-region) или выберите пункт Tag Region меню Markup, после чего PSGML вставит открывающий тэг в начало блока(region) и закрывающий тэг в конец. (Помните, что понятие "блок" (region) аналогично понятию выделенного блока в других текстовых процессорах и текстовых редакторах, и означает фрагмент текста между последним началом выделения и текущим местоположением курсора.)
Некоторые версии редактора Emacs не выделяют цветом блок, поэтому легко забыть, где были поставлены маркеры начала и конца блока. При этом команда sgml-tag-region может вставить открывающий и закрывающий тэги совсем не там, где ожидалось. Чтобы избежать подобной ситуации, нужно помнить о комбинации клавиш C-x C-x (команда exchange-point-and-mark), которая позволяет быстрым перемещением курсора проверить границы блока.
Команды sgml-insert-tag и sgml-insert-end-tag позволяют вставлять открывающий и закрывающий тэги независимо друг от друга. Нажмите C-c < (или выберите Insert Start-Tag в меню SGML), чтобы вставить открывающий тэг. Закрывающий тэг вставляется через нажатие C-c / (или Insert End-Tag в меню SGML).
Если версия редактора позволяет использовать меню, выберите пункт Insert Element из меню Markup. Появится еще одно меню со списком элементов, доступных для вставки в текущую позицию курсора. Если для вставки доступен только один элемент, то открывшееся меню будет состоять из одного пункта. Если допустимых типов элементов слишком много, то Emacs разобьет их на несколько дополнительных меню.
Чтобы вставить только отрывающий, или только закрывающий, тэг воспользуйтесь пунктом Insert Start-Tag (открывающий тэг) или Insert End-Tag.
Для выравнивания текста, как было показано выше, используется комбинация клавиш M-q (команда fill-paragraph). Эта команда выравнивает длину строк в соответствии с установленной правой границей. В тексте SGML целесообразно использовать другую команду: sgml-fill-element, вызываемую нажатием C-c C-q или выбором пункта Fill Element меню Modify.
Команда sgml-fill-element, в отличие от команды fill-paragraph, выравнивает текст только внутри одного элемента, сохраняя при этом общую структуру. Рассмотрим это на следующем примере:
<sect1> <title>The Chase--Third Day</title> <para>But aye, old mast, we both grow old together; sound in our hulls, though, are we not, my ship? Aye, minus a leg, that's all. By heaven this dead wood has the better of my live flesh every way.</para> <para>I can't compare with it; and I've known some ships made of dead trees outlast the lives of men made of the most vital stuff of vital fathers. <emphasis>What s that he said?</emphasis> he should still go bef\ ore me, my pilot; and yet to be seen again? But where? Will I have eyes at the bottom of the sea, supposing I descend those endless stairs and all night I've been sailing from him, wherever he did sink to.</para> </sect1> |
После применения команды sgml-fill-element текст будет выглядеть следующим образом:
<sect1> <title>The Chase--Third Day</title> <para>But aye, old mast, we both grow old together; sound in our hulls, though, are we not, my ship? Aye, minus a leg, that's all. By heaven this dead wood has the better of my live flesh every way.</para> <para>I can't compare with it; and I've known some ships made of dead trees outlast the lives of men made of the most vital stuff of vital fathers. <emphasis>What s that he said?</emphasis> he should still go before me, my pilot; and yet to be seen again? But where? Will I have eyes at the bottom of the sea, supposing I descend those endless stairs and all night I've been sailing from him, wherever he did sink to.</para> </sect1> |
Изменилась только та часть текста, которая следовала после тэга <emphаsis>, общая структура текста, включая разбивку на параграфы, осталась нетронутой. В случае применения команды fill-paragraph данный текст представлял бы собою единый блок, без разбивки на параграфы.
В главе "Настройка переменных редактора Emacs" говорилось о том, что переменная sgml-indent-step позволяет осуществлять автоматическое структурирование тэгов PSGML, путем смещения вложенных элементов на требуемое количество символов вправо. В Emacs существует команда, которая в режиме PSGML выравнивает тэги. Это команда indent-region, соответствующая комбинация клавиш - M-C-\.
Рассмотрим пример. Ниже приводится текст, в котором структурирование выполнено случайным образом.
<sect2> <title>A Bosom Friend</title> <para>We then turned over the book together, and I endeavored to explain to him the purpose of the printing, and the meaning of the few pictures that were in it.</para> <figure> <title>A Sample Figure</title> <graphic fileref="giftest.gif" format="gif"></graphic> </figure> <para>Thus I soon engaged his interest; and from that we went to jabbering the best we could about the various outer sights to be seen in this famous town.</para> |
Выделите данный текст как блок и нажмите M-C-\. PSGML обработает выделенный фрагмент, сделав структуру элементов более понятной:
<sect2> <title>A Bosom Friend</title> <para>We then turned over the book together, and I endeavored to explain to him the purpose of the printing, and the meaning of the few pictures that were in it.</para> <figure> <title>A Sample Figure</title> <graphic fileref="giftest.gif" format="gif"></graphic> </figure> <para>Thus I soon engaged his interest; and from that we went to jabbering the best we could about the various outer sights to be seen in this famous town.</para> |
В главе "Перемещение курсора" говорилось о том, каким образом переместить курсор на один символ или слово влево или вправо, на строку вверх или вниз. PSGML усложняет структуру документа, в связи с чем возникают дополнительные требования к возможностям перемещения курсора.
Облегчить запоминание комбинаций клавиш перемещения курсора в режиме SGML, поможет тот факт, что в большинстве случаев клавиши, выполняющие аналогичные действия в Emacs и SGML, отличаются наличием в SGML-комбинациях клавиши Escape.
В Emacs перемещение курсора в начало и конец текущей строки осуществляется комбинациями клавиш C-a и C-e. PSGML-комбинации, осуществляющие перевод курсора в начало и конец текущего элемента выглядят как C-M-a (команда sgml-beginning-of-element) и C-M-e (команда sgml-end-of-element), также можно воспользоваться пунктами Beginning of element и End of element меню Move.
Чтобы "перепрыгнуть" на элемент вперед или назад, воспользуйтесь комбинацией C-M-f (sgml-forward-element) и C-M-b (sgml-backward-element) соответственно, либо воспользуйтесь пунктами Forward element и Backward element меню Move. Данные команды осуществляют перемещение по вложенным элементам. Например, если в элементе para при перемещении вперед был достигнут последний вложенный элемент, то в окне минибуфера появится сообщение:
No more elements in para element |
То же самое сообщение появится при попытке перемещения вперед внутри элемента, не содержащего вложенных элементов.
Sgml-backward-element ведет себя совершенно аналогично при достижении первого вложенного элемента.
Команды sgml-forward-element и sgml-backward-element демонстрируют интеллектуальные возможности PSGML, поскольку PSGML воспринимает документ не как простую совокупность текста и тэгов, а скорее как структурированный текст, в котором одни элементы являются частью других элементов, и все они объединены в определенной структуре. Три другие команды, которые используют преимущества структурированности документа, призваны помочь передвигаться по документу. Речь идет о командах sgml-down-element, sgml-up-element, и sgml-up-backward-element. (В дополнение к комбинациям клавиш, которые будут описаны ниже, имеет смысл упомянуть о пунктах Up element, Down element и Backward up element меню Move.) В данном случае перемещение "вверх" ("Up") и "вниз" ("Down") следует понимать в смысле перемещения вверх и вниз по уровням иерархии документа.
Нажатие C-M-d (команда sgml-down-element) осуществляет перемещение курсора вниз по иерархии документа, курсор перемещается в первую позицию после открывающего тэга.
При продвижении по иерархии элементов, имеется выбор перемещения курсора вперед или назад к пункту в родительском элементе текущего элемента. Команда sgml-up-element осуществляет перемещение по иерархии вверх. Запуск команды осуществляется нажатием комбинации клавиш C-c C-n. При нажатии данной комбинации курсор перемещается вперед по документу и вверх по иерархии. Т.е., если, например курсор был установлен внутри параграфа, то после нажатия C-c C-n, курсор будет установлен в первой позиции после закрывающего тэга данного параграфа. При повторном нажатии курсор перейдет в первую позицию после закрывающего тэга главы и т.д.
Перемещение курсора вверх по документу и вверх по иерархии осуществляется командой sgml-backward-up-element (комбинация клавиш C-M-u). При нажатии комбинации C-M-u курсор перемещается назад по документу и вверх по иерархии. Т.е., если, например курсор был установлен внутри параграфа, то после нажатия C-M-u, курсор будет установлен в первой позиции перед открывающим тэгом данного параграфа. При повторном нажатии курсор перейдет в первую позицию перед открывающим тэгом главы и т.д.
Другая полезная при перемещении курсора команда - это sgml-next-data-field (соответствующая комбинация - C-c C-d). Данная команда перемещает курсор в следующую позицию, где доступен ввод текстовой информации. Например, если курсор был установлен внутри параграфа, то после нажатия C-c С-d, курсор будет установлен после открывающего тэга следующего параграфа. Если внутри следующего параграфа есть вложенные элементы, внутри которых возможен ввод текста, то при повторном нажатии курсор будет установлен после открывающего тэга следующего вложенного элемента. Альтенативный способ запуска команды sgml-next-data-field - пункт Next Data Field меню Move.
Команда sgml-next-data-field бывает особенно полезной в случае вставки нескольких вложенных элементов командой sgml-insert-element (комбинация C-c C-e), когда не требуется немедленный ввод текста в каждый из элементов. Осуществлять навигацию по созданной структуре удобно нажатием C-c C-d.
Ранее уже обсуждались возможности редактора Emacs по удалению, копированию и перемещению выделенных блоков текста. Аналогичные операцию можно выполнять с элементами SGML.
Чтобы удалить элемент SGML, можно воспользоваться стандартным способом, т.е. выделить блок от открывающего тэга до закрывающего, а затем нажать C-w. Но есть способ лучше. Команда PSGML sgml-kill-element (комбинация C-M-k) удаляет текст внутри элемента начиная с текущей позиции курсора и до закрывающего тэга. Альтернативный вызов команды из меню Modify - пункт Kill element. При использовании команды sgml-kill-element всегда следует помнить о команде отката - undo (C-_).
Если после удаления текста вторично нажать C-M-k, то в окне минибуфера появится сообщение:
No more elements in название_элемента element |
Команду sgml-kill-element можно использовать для перемещения текста. Элемент, помещенный данной командой в буфер обмена, может быть потом вставлен в нужное место командой yank (C-y).
Перед тем, как перейти к рассмотрению вопросов, связанных с копированием элементов, обратим внимание на работу двух команд: sgml-untag-element и sgml-kill-markup.
Команда sgml-untag-element (комбинация C-c -) удаляет открывающий и закрывающий тэги текущего элемента. Альтернативный вызов команды через пункт Untag Element меню Modify.
Команда sgml-kill-markup (комбинация C-c C-k или пункт Markup меню Modify) удаляет в буфер фрагмент текста, заключенного между символами "<" и ">". Эта команда полезна для удаления комментариев, которые PSGML вставляет около элементов, если переменной sgml-auto-insert-required-elements присвоено ненулевое значение.
PSGML не имеет встроенной команды для удаления текста от текущей позиции до конца элемента. Данный пробел можно восполнить, добавив следующий макрос в файл .emacs:
(defun sgml-kill-to-eoelement () ; kill to end of element (interactive) (let ((start (point))) (sgml-end-of-element) (kill-region start (point)))) ; assign to ^Ck keystrokes (define-key global-map "^Ck" sgml-kill-to-eoelement) |
Существуют два способа копирования элементов со всеми подэлементами. Первый способ - это использовать описанные выше комбинации клавиш, чтобы удалить элемент со всеми вложенными элементами и тут же его вставить. Другой способ предусматривает копирование элемента в буфер обмена без удаления. Чтобы проделать это, нужно выполнить следующие шаги:
Чтобы ускорить процедуру копирования элемента в буфер обмена, можно оформить описанную выше процедуру в виде макроса в файле .emacs. Запуск этого макроса пускай будет осуществляться комбинацией клавиш C-c w. Текст макроса, копирующего текущий элемент в буфер обмена выглядит следующим образом:
(defun sgml-copy-element () (interactive) (sgml-backward-up-element) (let ((start (point))) (sgml-forward-element) (kill-ring-save start (point)))) ; assign to ^Cw keystroke (define-key global-map "^Cw" sgml-copy-element) |
Существует четыре способа редактирования атрибутов, включая возможности меню PSGML. Первый способ - просто пеместить курсор в открывающий тэг элемента и набрать имя атрибута и его значение. Рассмотрим пример:
<p>Now, the Pequod had sailed from <a>Nantucked</a> at the very beginning of the Season-on-the-line.</p> |
Пусть нужно добавить атрибут HREF в элемент a. Для этого переместите курсор, установив его на открывающем тэге так, чтобы курсор был установлен на символе ">", и наберите имя атрибута и его значение. В результате должно получиться следующее:
<p>Now, the Pequod had sailed from <a href="http://www.nantucket.com">Nantucket\ </a> at the very beginning of the Season-on-the-line.</p> |
Конечно, описанную выше процедуру можно выполнить в любом текстовом редакторе. Ниже будут рассмотрены методы редактирования атрибутов, использующие преимущества PSGML. Сама процедура редактирования значительно упрощается.
Команда PSGML sgml-insert-attribute (комбинация C-c + или пункт Insert Attribute меню Markup) представляет более универсаленый способ вставки атрибутов, поскольку предоставляет возможность выбора не только имен, но и допустимых значений. Установите курсор либо на открывающем тэге, либо на закрывающем, либо в области ввода текста данного элемента и нажимите C-c +. В окне минибуфера отобразится подсказка:
Attribute name: |
После того, как имя атрибута введено в окне минибуфера и нажат Enter, в окне минибуфера отображается имя атрибута (тип данных) и текущее значение (если значение атрибута не было оговорено особо), а также предлагается ввести новое значение. Вид экрана представлен на рис. Вид командной строки для команды ..
Не нужно набирать кавычки при вводе значения атрибута - PSGML добавляет их сам. В окне минибуфера введите значение атрибута: http: // www.nantucket.gov, как это показано на рис. Ввод нового значения аттрибута .,
и нажмите Enter. При этом значение атрибута должно быть изменено. Результат представлен на рис. Результат редактирования значения аттрибута ..
При вводе значений атрибутов также можно использовать функцию "дописывания", если объявленное значение является группой названий. Например, определением элемента HTML DTD IMG предусмотрено наличие атрибута ALIGN:
ALIGN (top|middle|bottom) #IMPLIED |
При редактировании элемента IMG и его атрибута ALIGN после нажиматия C-c + и введите одну из трех букв: t, m, или b, а затем нажмите Tab. При этом значение атрибута будет введено полностью.
Другой, еще более простой способ редактирования атрибутов, особенно при необходимости редактирования более одного атрибута того же самого элемента, является использование команды sgml-edit-attributes (комбинация клавиш C-c C-a или пункт Edit Attributes меню Modify). В новом окне будет выведен список допустимых атрибутов текущего элемента в виде формы, которую нужно заполнить. Рассмотрим пример. Нажмите C-c C-a, предварительно поместив курсор на слове Nantucket. Вид экрана представлен на рис. Ввод значений аттрибутов с помощью команды ..
Переместите курсор на значение какого-нибудь другого атрибута и введите новое значение. Быстрый переход к полю значения следующего по списку атрибута осуществляется нажатием кнопки Tab. После того, как значения всех интересующих атрибутов были изменены, нажмите C-c C-c. При этом внесенные значения будут отображены в тексте документа, а окно атрибутов будет закрыто. Если нужно закрыть окно атрибутов без сохранения, нажмите C-x 0.
Режим "дописывания" не работает при вводе значений атрибутов, но в этом нет нужды, поскольку в окне редактирования атрибута перечислены возможные варианты значений всех атрибутов.
Например, на рис. Окно редактирования атрибута для элемента
.
показано окно редактирования атрибута для элемента HTML
IMG; обратите внимание на список "bottom
middle top" во второй строке атрибута
ALIGN:
Четвертый и самый простой способ редактирования атрибутов со значением - через пункт Insert Attribute от меню Markup, если, конечно, версия Emacs допускает использование меню. В отличие от команды вставки атрибута sgml-insert-attribute с быстрой клавишей C-c +, пункт Insert Attribute от меню Markup позволяет редактировать значения уже существующих атрибутов. Нужно просто поместить курсор в поле атрибута, вызвать пункт меню, выбрать тип атрибута, а затем выбрать новое значение атрибута из предложенных.
Как было показано ранее самый быстрый способ активировать PSGML после загрузки документа - это запустить команду sgml-next-trouble-spot (C-c C-o). Для многих пользователей PSGML это привычная процедура.
Следует неоднократно повторять данную процедуру в процессе работы. Например, всякий раз перед сохранением документа, чтобы быть уверенным, что структура сохраняемого документа не содержит ошибок. Переместите курсор в начало документа, или начало той части документа, которую необходимо проверить и нажмите C-c C-o. Если в окне минибуфера появится сообщение "Ok", значит PSGML не обнаружил каких бы то ни было проблем.
Следует помнить, что команда PSGML sgml-next-trouble-spot не выполняет полный синтаксический анализ, а только помогает отследить явные ошибки. Чтобы проверить текст надлежащим образом, нажмите комбинацию клавиш C-c C-v (команда sgml-validate. По этой команде экран будет разбит на два окна, в одном из которых будут выводиться сообщения о процессе выполнения синтаксического анализа документа, в том числе и сообщения об ошибках, если таковые будут обнаружены. окне. По умолчанию в PSGML установлен синтаксический анализатор 0.4 beta 2 nsgml. Это свободно распространяемая версия синтаксического анализатора, разработанного Джеймсом Кларком. Ниже будет показано, как можно установить в PSGML другой синтаксический анализатор.
После нажатия C-c C-v (пункт Validate меню SGML), PSGML в окне минибуфера выведет сообщение о запускаемой на выполнение команде, которое при необходимости можно отредактировать:
Validate command: nsgmls -s whalin.sgm |
(Ключ s сообщает nsgmls, что нужно выводить только сообщения об ошибках и не отображать информацию о ходе синтаксического анализа.) Редактирование необходимо для вставки, если потребуется, имени файла, содержащего объявления SGML (SGML declarations), перед именем файла документа. Вызвано это тем, что nsgmls, являющийся достаточно полным синтаксическим анализатором, гораздо в большей степени заботится о конструкциях SGML, чем PSGML следует Reference Concrete Syntax. А поскольку Reference Concrete Syntax не позволяет названию типа элемента иметь более восьми символов, то nsgml будет выдавать двухстрочные сообщения об ошибках всякий раз, когда встретит где-либо в тексте подобную конструкцию.
Когда команда проверки синтаксиса появится в окне минибуфера, переместите курсор и введите имя файла, содержащего объявления SGML:
Validate command: nsgmls -s ..\catalog\docbook.dcl whalin.sgm |
Предполагается, что путь к программе синтаксического анализа установлен. Если PSGML не может найти nsgml, то появится соответствующее сообщение об ошибке в окне вывода.
После того, как команда nsgml отредактирована, и нажата клавиша Enter, PSGML разбивает экран пополам, чтобы создать новое окно для буфера под названием *sgml validation*. Вид команды, выполняющей проверку, отобразится в этом окне.
Если в окне минибуфера появится слово "done", то это означает, что программа проверки не нашла ошибок в тексте документа.
Если же ошибки все-таки обнаружены, то программа проверки перечислит их в окне буфера *sgml validation*. PSGML отсортирует сообщения и позволит быстро найти ошибки, обнаруженные в тексте. Рассмотрим пример. Добавим две ошибки к совершенно правильному тексту и посмотрим как будут выглядеть сообщения об ошибках.
Ниже приводится текст документа, который полность соответствует DocBook DTD, за исключением двух пунктов. Во-первых, в элемент emphasis помещен беспризорный открывающий тэг <sect1>, а во-вторых, в элемент <para> вставлен недопустимый атрибут hair со значением red:
<!DOCTYPE chapter PUBLIC "-//Davenport//DTD DocBook V2.4.1//EN"> <chapter> <title>Gone Whalin </title> <sect1> <title>The Carpet-Bag</title> <para>I stuffed a <emphasis>shirt<sect1></emphasis> or two into my old carpet-bag, <emphasis>tucked</emphasis> it under my arm, and <emphasis>started</emphasis> for Cape Horn and the Pacific.</para> <para hair=red>Quitting the good city of old Manhatto, I duly arrive in New Bedford.</para> <para>It was on a Saturday night in December.</para> |
Нажмите C-c C-v, чтобы отправить данный образец на проверку. Сообщения об ошибках будут выглядеть следующим образом:
nsgmls:whalin.sgm:6:43:E: document type does not allow element "SECT1" here nsgmls:whalin.sgm:6:54:E: "SECT1" not finished but containing element ended nsgmls:whalin.sgm:6:54:E: end tag for "SECT1" omitted, but OMITTAG NO was specified nsgmls:whalin.sgm:6:37: start tag was here nsgmls:whalin.sgm:9:15:E: there is no attribute "HAIR" nsgmls:whalin.sgm:11:57:E: end tag for "SECT1" omitted, but OMITTAG NO was specified nsgmls:whalin.sgm:4:1: start tag was here nsgmls:whalin.sgm:11:57:E: end tag for "CHAPTER" omitted, but OMITTAG NO was specified nsgmls:whalin.sgm:2:0: start tag was here |
Данные сообщения об ошибках дают два полезных урока, связанных с программированием вообще:
next-error (комбинация C-x ') - команда Emacs, осуществляющая переход в строку, где была обнаружена ошибка. Эта команда не является специфической командой PSGML. Она используется программистами для обнаружения строк в их исходном тексте программ, в которых компилятор нашел ошибки. По команде next-error курсор переходит в окно документа и перемещается в строку, содержащую ошибку. При этом в окне буфера сообщений об ошибках, *sgml validation*, соответствующее сообщение становится первым в списке (см. рис. Поиск ошибок в тексте с помощью команды .).
Посторонний тэг sect1 стал причиной пяти сообщений об ошибках, а атрибут hair - только одной. Сообщение без буквенного кода кода после второго номера не является самостоятельным сообщением об ошибке, а несет в себе дополнительную информацию для предыдущей ошибки. Последовательно нажимая C-x ' можно отследить все "множественные" ошибки.
Если ошибок больше нет, и при этом нажать C-x ', то в окне минибуфера появится сообщение:
No_more_errors |
Для сохранения команды проверки синтаксиса (той самой, которая запускается нажатием C-c C-v), PSGML создает в среде Emacs переменную sgml-validate-command. Если нужно изменить команду, то измените значение этой переменной в файле .emacs. Пусть, например, при вызове команды describe-variable (C-h v) Emacs выдает, что переменная sgml-validate-command имеет следующее значение:
nsgmls -s %s %s |
(%s %s показывает, куда Emacs при выполнении данной команды вставляет имена редактируемых файлов. Синтаксис команды наверняка знаком С-программистам.) Если нужно, чтобы PSGML, запускал при нажатии C-c C-v sgmls вместо nsgml, отредактируйте следующую строку в .emacs-файле:
(setq sgml-validate-command "sgmls -s %s %s") |
Помните, команда проверки может нуждаться в файле объявлений SGML. Если при работе часто используется один и тот же файл объявлений SGML, можно добавить его в строку .emacs, устанавливающей значение переменной sgml_validate_command:
(setq sgml-validate-command sgmls -s \\sgml\\dtds\\docbook.dcl %s %s ) |
(Обратите внимание на использование двойных обратных слешей для того, чтобы поместить обратные слеши в строку команды.) Естественно, что в случае ненадобности использования файла объявлений SGML, сохраняется возможность редактирования команды после нажатия C-c C-v.
PSGML обладает слишком широкими возможностями, чтобы их можно было описать в одной главе. Однако, несколько наиболее ценных свойств заслуживают особого внимания.
При использовании терминала (или программы эмуляции терминала) и версии Emacs, поддерживающей отображение текста различным шрифтом или цветом, PSGML может использовать эти возможности для облегчения восприятия разных видов разметки. Настройки PSGML по умолчанию отображают комментарии SGML курсивом; ссылки на объект - полужирным курсивом; тэги, встроенные инструкции, SGML и DOCTYPE объявления, а также короткие ссылки - полужирным шрифтом.
Если используемая версия Emacs может работать с различными шрифтами, то скорее всего это версия редактора под UNIX с XWINDOWS терминалом. Другие версии обычно вместо различных шрифтов используют выделение цветом. Так поступает, например, EMX версия GNU Emacs 19.29.2, отображая комментарии красным, ссылки на объект желтым, и тэги и прочую разметку белым цветом на общем сером фоне.
Если была использована команда sgml-next-trouble-spot, а выделение шрифтом или цветом отсутствует, то можно задать Emacs и PSGML отображать разметку выбранным способом, добавив несколько строк к .emacs-файл. Создание этих строк можно разбить на следующие четыре этапа:
Ниже приводится код .emacs, демонстрирующий назначение разметки цветом для комментариев, тэгов, и ссылки на объект.
;;;;; Assign colors to markup. ;;;;; ; Create faces to assign to markup categories. (make-face sgml-comment-face) (make-face sgml-start-tag-face) (make-face sgml-end-tag-face) (make-face sgml-entity-face) ; Assign attributes to faces. Background of white assumed. (set-face-foreground sgml-comment-face "White") ; Comments: white on (set-face-background sgml-comment-face "Gray") ; gray. (set-face-background sgml-start-tag-face "Gray") ; Tags: black (default) (set-face-background sgml-end-tag-face "Gray") ; on gray. (set-face-foreground sgml-entity-face "White") ; Entity references: (set-face-background sgml-entity-face "Black") ; white on black. ; Assign faces to markup categories. (setq sgml-markup-faces '((comment . sgml-comment-face) (start-tag . sgml-start-tag-face) (end-tag . sgml-end-tag-face) (entity . sgml-entity-face))) ; Tell PSGML to pay attention to face settings. (setq sgml-set-face t) |
Команда sgml-normalize разворачивает любые пустые тэги и заполняет пропущенные тэги в образце документа. Другими словами, данная команда проверяет, что каждый непустой элемент имеет открывающий и закрывающий тэги, в соответствии с требованиями DTD.
Большое количество программного обеспечения SGML требуют нормализованного SGML, поэтому данная команда - быстрый способ подготовить документ к использованию с подобного рода программами. Эта команда не имеет назначенной комбинации клавиш, потому что не часто используется. Ее вызов можно осуществить либо из командной строки минибуфера (M-x), либо через пункт Normalize меню Modify.
Команда sgml-complete (М-Tab) помогает завершить ссылку на объект, тэг, или любой заранее определенный набор слов и символов. Ранее было показано, что PSGML может "дописывать" названия типа элемента. Аналогичный режим возможен при вводе ссылок.
PSGML распознает режим ввода ссылок, когда пользователь вводит амперсанд. После этого можно M-Tab, и в отдельном окне появится список всех допустимых объекты. Если после амперсанда введено достаточное количество символов, то PSGML "допишет" название ссылки, как это происходит в случае с названиями элементов.
Команда sgml-complete "дописывает" также объявления разметки, которые чаще всего используются в DTD, чем в тексте документа. Например, введите "<!" и нажмите M-Tab. Откроется новое окно, содержащее следующий список возможных завершений:
sgml | doctype |
element | entity |
usemap | shortref |
notation | attlist |
uselink | linktype |
link | idlink |
В главе "Настройка переменных редактора Emacs" говорилось о необходимости присвоения ненулевого значения переменной sgml-live-element-indicator, чтобы сообщить PSGML о необходимости отображения типа документа и имени текущего элемента в строке состояния. Более подробную информацию о месте текущего элемента в общей структуре документа, можно получить с помощью команды sgml-show-context (C-c C-c). Информация о месте текущего элемента в иерархии документа выводится в окне минибуфера.
<sect1> <title>Biographical</title> <para>Queequeg was a native of <emphasis>Kokovoko</emphasis>, an island far away to the West and South.</para> |
Например, переместите курсор в приведенном выше тексте на слове "Kokovoko" и нажмите C-c C-c. В окне минибуфера появится следующее сообщение:
#PCDATA in emphasis in para in sect1 in chapter |
Альтернативный вызов - пункт Show Context меню SGML.
C-f | forward-char | Перемещение на один символ вправо |
C-b | backward-char | Перемещение на один символ влево |
C-Left | backward-word | Перемещение на одно слово влево |
M-b | previous-word | Перемещение на одно слово влево |
C-Right | backward-word | Перемещение на одно слово вправо |
M-f | next-word | Перемещение на одно слово вправо |
C-v | scroll-up | Перемещение на одну страницу вперед |
C-a | beginning-of-line | Перемещение в начало строки |
C-e | end-of-line | Перемещение в конец строки |
M-v | previous-page | Перемещение на одну страницу назад |
M-b | previous-word | Перемещение на одно слово влево |
M-f | next-word | Перемещение на одно слово вправо |
C-p | previous-line | перемещение на одну строку вверх |
C-n | next-line | перемещение на одну строку вниз |
C-M-a | sgml-beginning-of-element | Перемещение на первый символ данных текущего элемента |
C-M-e | sgml-end-of-element | Перемещение на последний символ данных текущего элемента |
C-c C-d | sgml-next-data-field | Перемещение курсора в следующую позицию, где можно вводить данные |
C-c C-n | sgml-up-element | Перемещение вверх по иерархии элементов в конец закрывающего тэга |
C-M-u | sgml-backward-up-element | Перемещение вверх по иерархии элементов в начало открывающего тэга |
C-M-d | sgml-backward-element | Перемещение в начало следующего вложенного элемента |
C-M-f | sgml-forward-element | Перемещение в конец следующего вложенного элемента |
C-d | delete-char | Удаление символа |
C-@ | set-mark-command | Начало выделения |
C-space | set-mark-command | Начало выделения |
C-w | kill-region | Удаление выделенной области в буфер обмена |
C-k | kill-line | Удаление фрагмента от курсора до конца строки |
C-x C-x | exchange-point-and-mark | "Перепрыгивание" курсора в начало/конец выделенного блока |
C-y | yank | Вставка удаленного текста в текущую позицию |
M-d | kill word | Удаление слова |
M-i | overwrite-mode | Переключатель Insert/Replace. Нестандартная команда Emacs, установленная строкой в файле ".emacs". |
M-q | fill-paragraph | Выравнивание параграфа |
M-w | kill-ring-save | Копировать в буфер обмена (kill ring) |
M-y | yank-pop | Последовательная вставка в текущую позицию блоков, помещенных в буфер kill ring |
M-C-\ | indent-region | Выравнивание строк выделенного фрагмента. В режиме PSGML - выравнивание тэгов, чтобы раскрыть структуру элемента. |
C-q | quoted-insert | Вставка символьного эквивалента нажатой клавиши, даже если это командная комбинация |
C-c C-e | sgml-insert-element | Ввод элемента через командную строку минибуфера |
С-с < | sgml-insert-tag | Вставка открывающего тэга. Удобно использовать при добавлении тэгов к существующему тексту, поскольку содержание элемента можно редактировать |
C-c / | sgml-insert-end-tag | Вставка закрывающего тэга. Удобно использовать при добавлении тэгов к существующему тексту |
C-c C-r | sgml-tag-region | Вставка открывающего и закрывающего тэгов элемента для выделенного фрагмента текста |
C-c - | sgml-untag-element | Удаление открывающего и закрывающего тэгов элемента. |
C-c C-k | sgml-kill-markup | Удаление отмеченного курсором тэга |
C-c Enter | sgml-split-element | Или, "вставить новый элемент, идентичный текущему". Разбить элемент вставкой закрывающего и открывающего тэгов |
C-c o | sgml-comment | Макро-вставка в .emacs-файл. См. описание |
C-M-k | sgml-kill-element | Удаление текста от текущей позиции курсора до конца следующего вложенного элемента |
M-Tab | sgml-complete | Режим "дописывания" при вводе тэгов и других значимых слов |
C-c C-q | sgml-fill-element | Выравнивание текущего элемента |
C-c + | sgml-insert-attribute | Редактирование атрибутов текущего элемента с использованием подсказки |
C-c C-a | sgml-edit-attributes | Редактирование атрибутов текущего элемента с использованием формы в отдельном окне Emacs |
C-h | Меню справочных средств | |
C-h ? | help-for-help | Описание использования встроенной подсказки |
C-h a | command-apropos | Вывод на экран всех команд, где встречается указанное выражение |
C-h k | describe key | Вывод описания комбинации клавиш, нажатой после C-h k |
C-c C-c | sgml-show-context | Или, после C-c C-a, завершение редактирования атрибутов |
C-x ' | next-error | Найти следующую ошибку в окне сообщений об ошибках |
C-c C-o | sgml-next-trouble-spot | Переместить курсор к следующей потенциальной проблеме |
C-c C-v | sgml-validate | Отправить документ на обработку |
C-x 0 | delete-window | Закрыть текущее окно |
C-x 1 | delete-other-windows | Закрыть все окна, кроме текущего |
C-x 2 | split-window-vertically | Разделить окно по горизонтали |
C-x o | other-window | Переход в другое окно |
C-x b | switch-to-buffer | Отобразить другой буфер в текущем окне |
C-x C-b | list-buffers | Отобразить список открытых буферов в новом окне |
C-x C-s | save-buffer | Сохранить содержимое буфера в файле на диске |
C-x C-w | write-file | Сохранить содержимое буфера в файле на диске под новым именем (если нужно) |
C-x C-c | save-buffers-kill-emacs | Перед выходом из редактора запросить о необходимости сохранения измененных файлов |
C-x C-f | find-file | Открывает и считывает файл в буфер |
C-x i | insert-file | Вставка содержимое файла в буфер в текущую позицию |
C-g | keyboard-quit | Прекращение текущей многошаговой операции |
C-_ | undo | Откат последней команды |
C-x ( | start-kbd-macro | Начать запись макрокоманды |
C-x ) | end-kbd-macro | Закончить запись макрокоманды |
C-x e | call-last-kbd-macro | Выполнить последнюю записаную макрокоманду |
C-u (number) C-x f | set-fill-column | Устанавливает правую границу в столбце (number) |
M-x | execute-extended-command | Отображение командной строки в окне минибуфера |
C-s | isearch-forward | Прямой инкрементный (пошаговый) поиск |
C-r | isearch-backward | Обратный инкрементный (пошаговый) поиск |
M-% | query-replace | Предлагает ввести образец для поиска и текст для замены |
Последние изменения: Ср 26 Дек 2001 12:55:50
Сгенерировано TEItools