Написание документации, часть 1: POD
Автор: (C) Кристоф Шпиль [Christoph
Spiel]
Перевод: (C) Сергей Скороходов
Название Написание документации звучит немного официально. В статье я, однако, буду говорить о документации в широком смысле, т.е. не только о конкретном наборе документов, сопровождающем конкретную программу, а о любом похожем тексте справочно-информационного характера. Такой источник может оказаться всего несколькими строками, объясняющими, как запускать программу, описывающими опции командной строки и правильную установку переменных окружения. С другой стороны, это могут быть тысячи строк, в деталях описывающие все тонкости и приемы, добытые группой людей за многие годы работы с большой программной системой.
Вдохновенному техническому писателю привольно живется в современных дистрибутивах GNU/Linux, где ему на выбор предлагается несколько систем для написания документации! В данной серии статей я расскажу про три. Сегодня я начну с POD. В следующем месяце мы поговорим о LaTeX в соединении с latex2html, а в части третьей -- о DocBook.
Каждая из этих систем удовлетворяет определенным требованиям и имеет как сильные, так и слабые стороны. Но, прежде чем обсуждать все за и против конкретных систем, позвольте остановиться на том, что я требую от системы технической документации. Итак.
Исходный текст будущей документации должен обладать следующими свойствами:
В декабре 2001 года "переносимость" практически подразумевает текст в 7-битной кодировке ASCII. Сегодня только семибитная кодировка ASCII работает на огромном числе компьютерных платформ. В будущем, надеюсь, это будет означать Unicode. В Unicode можно представить значительно больший репертуар символов, и это будет столь же переносимым.
Требование переносимости означает, что исходные тексты можно будет прочесть и отредактировать на разнообразных компьютерных системах. Это открывает для других программистов доступ к документации, в чем и заключается смысл программного обеспечения с открытым исходным текстом.
Компьютерные данные хороши настолько, насколько их можно легко найти. -- Звучит, как избитая истина, но мы легко забываем про то, что документацию следует поддерживать в актуальном состоянии точно так же, как и исходный код программы. Нам нужна возможность найти в текстах, скажем, конкретный термин или идентификатор. Следовательно, исходный текст документации должен быть, по крайней мере, пригоден для обработки стандартными средствами полнотекстового поиска, например семейства grep (grep, agrep, rgrep, sgrep).
Крайне желательно (если мы, конечно, не ограничиваемся крохотными заметками), чтобы исходный текст можно было разделить на логические части, например, на разделы. Тем не менее, система создания технической документации должна обрабатывать полный набор исходных файлов как единое целое.
Для того чтобы документация была "открытой" (в смысле Open Source), исходный текст должен быть легко читаем, а создание окончательного "компилированного" варианта -- легко в освоении. Больше шансов на успех имеет та система написания документации, в которой автор (а в дальнейшем, возможно, и тот, кто будет поддерживать ее в актуальном состоянии) сможет сконцентрироваться на содержании, а не на изучении синтаксических ухищрений или неочевидной последовательности применения программных утилит, необходимой для получения окончательной скомпилированной версии.
Я предъявляю определенные требования не только к исходным текстам, но и к "выходному" формату.
Система документации должна позволять создавать документы в различных форматах, чем больше их будет -- тем лучше. Минимально должны поддерживаться HTML и PostScript (некоторые предпочтут PDF), первый для чтения с экрана, а второй -- для распечатки.
В свою очередь, поддержка HTML предполагает гиперссылки, предоставляющие удобную возможность перехода на определенные места в других документах или к другим частям того же документа. Помимо всего, ссылки облегчают реализацию требования модульности для исходных текстов.
Автоматическое создание ссылок
Насколько это возможно, ссылки должны разрешаться автоматически. Например, система должна без участия пишущего разрешать перекрестные ссылки внутри документа, а также размещать и нумеровать сноски и выноски. Список библиографии тоже должен создаваться автоматически.
А теперь давайте взглянем на самый несложный формат: Perl's Plain Old Documentation [старая добрая простая документация Perl].
Система "Plain Old Documentation", которая входит в каждый дистрибутив Perl -- самая простая из всех, которые я отобрал для этого цикла статей. Проста в изучении и использовании, но (не хотелось бы говорить "вследствие этого") ее возможности -- самые ограниченные. Так или иначе, но статья, которую вы в данный момент читаете (да, именно так!) была подготовлена в POD'е. А если этот соус годится с гусыней, то и гусаку он не навредит...
У POD есть серьезные преимущества
pod2man --help
чтобы узнать, установлена ли POD.
Формат POD определяет абзацы трех разных типов. Абзацы отделяются друг от друга одной или большим числом совершенно(!) пустых строк.
Абзац с обычным текстом [Ordinary Paragraph]
Любая строка, не начинающаяся, по крайней мере, с четырех пробелов или знака равенства считается обыкновенным текстом. Пустая строка служит разделителем абзацев. Это означает, что документ записывается один абзац за другим, каждый из которых отделяется, по крайней мере, одной пустой строкой.
При окончательном выводе обычные абзацы выравниваются (если формат допускает выравнивание), при необходимости с добавлением пробелов.
Абзац с преформатированным текстом [Verbatim Paragraph]
Строки с отступом в четыре и более пробелов рассматриваются, как преформатированный текст. В окончательном виде они выводятся точно так, как набраны. Все инструкции форматирования, о которых мы будем говорить далее, в преформатированных абзацах не действуют.
Абзац-команда [Command Paragraph]
Команды начинаются со знака равенства "=" в нулевой колонке, за которым немедленно следует идентификатор. Обычно команда состоит из одной строки. Тем не менее, синтаксически команды являются абзацами, поскольку отделяются пустыми строками перед и после ними.
Разделы текста отделяются командами =head
N,
например
=head1 заголовок_первого_уровня =head2 заголовок_второго_уровня =head3 заголовок_третьего_уровня
Эти же команды определяют заголовки разделов заголовок_первого_уровня и т.д. Сколько уровней вложенности заголовков (т.е. максимально допустимое N) разрешается -- зависит от конвертора POD-во-что-то-еще. Например, pod2man допускает только два уровня, pos2html -- до шести уровней.
К исходному тексту примеров я добавил номера колонок. Номера строк в настоящем исходном тексте отсутствуют. Здесь они включены для того, чтобы указать на пустые строки, которые должны разделять командные абзацы, т.е. те, которые начинаются со знака равенства в колонке 0. Для того чтобы сделать более понятным, где начинается нулевая колонка, в примере ниже я добавил линейку с делениями.
Пример:
1 2 3 4 5 012345678901234567890123456789012345678901234567890 1 =head1 Аппаратное обеспечение 2 3 Физические составляющие части вашего компьютера 4 называются аппаратным обеспечением, или hardware. 5 6 =head1 Процессор 7 8 Процессор (CPU) -- это самая важная деталь вашего 9 компьютера. 10 11 =head1 Устройства хранения данных 12 13 Устройства хранения данных, или mass storage devices 14 служат для постоянного хранения информации. 15 16 =head2 Жесткие диски 17 18 Жесткие диски (hard disk drives) обеспечивают произвольный 19 доступ к данным. 20 21 =head2 Магнитные ленты 22 23 Магнитные ленты (magnetic tapes) обеспечивают медленный 24 последовательный доступ к данным. 25 26 =head1 Программное обеспечение 27 28 Вот тут-то и начинаются вилы...
Ненумерованные списки, нумерованные списки или списки определений оформляются следующим образом
=over
N
=item
label
=item
label
...
=back
где команда =over
N начинает список, который
оформляется отступом, по крайней мере, в N пробелов и продолжается до
команды =back.
В зависимости от первого label транслятор
POD-во-что-то-другое создает ненумерованный список (label =
*
), нумерованный список (label = 1
) или
список определений (label начинается с буквы).
Пример: ненумерованный список
Я снова добавил номера строк для того, чтобы обратить внимание читателя на большое число пустых строк, разделяющих команды друг от друга.
Исходный текст
1 =over 4 2 3 =item * 4 5 Фрукты, особенно такие местно произрастающие фрукты, как ... 6 7 =item * 8 9 Хотя и не слишком вкусные, овощи составляют 10 значительную часть вашего повседневного рациона. 11 12 =item * 13 14 Рыба усваивается значительно лучше мяса. Следовательно, ... 15 16 =back
Результат
Пример: нумерованный список
Исходный текст
1 =over 4 2 3 =item 1. 4 5 Убедитесь, что рычажок включения питания находится в положении "ВЫКЛ.". 6 7 =item 2. 8 9 Подсоедините шнур питания. 10 11 =item 3. 12 13 Переместите рычажок включения питания в положение "ВКЛ.". 14 15 =back
Результат
Пример: список определений
Исходный текст
1 =over 8 2 3 =item Роберт 4 5 Солист 6 7 =item Джимми 8 9 Соло-гитара 10 11 =item Джон-Пол 12 13 Бас-гитара 14 15 =item Джон 16 17 Ударные 18 19 =back
Результат
Солист
Соло-гитара
Бас-гитара
Ударные
Внутри абзаца с обычным текстом действуют несколько команд разметки, задающие вид текста в выходном формате. Все они начинаются с заглавной буквы, далее следует аргумент, заключенный в угловые скобки: LETTER<argument>. Аргумент может состоять из нескольких слов и занимать более одной строки.
Аргумент выводится курсивом. I
соответствует
HTML-тэгам em
и var
, что обычно используется для
выделения слов или обозначения переменных.
Примеры:
Не стоит удалять с машины ядро Linux!
образуется из такой строки:
I<Не стоит> удалять с машины ядро Linux!
Сменить рабочую директорию на directory можно командой cd directory.
порождается
Сменить рабочую директорию на I<directory> можно командой B<cd> I<directory>.
Аргумент выводится жирным шрифтом. B
соответствует тэгу HTML
b
. Используется для выделения текста, названий программ и ключей
командной строки.
Примеры:
Всегда выполняйте команду shutdown перед тем, как отключить питание.
является результатом
B<Всегда> выполняйте команду shutdown перед тем, как отключить питание.
podchecker допускает опции -warnings и -nowarnings.
появляется из
B<podchecker> допускает опции B<-warnings> и B<-nowarnings>.
C
обозначает код или другой текст, который надо изобразить, как
есть, буквально. Соответствует тэгам HTML code
, samp
,
и tt
.
Примеры:
Каждая C-программа должна содержать функцию по имени main
.
порождается
Каждая C-программа должна содержать функцию по имени C<main>.
Логическое значение ЛОЖЬ представляется [1 1 0]
, а логическая
ИСТИНА -- [1 1 1]
.
порождается
Логическое значение ЛОЖЬ представляется C<[1 1 0]>, а логическая ИСТИНА -- C<[1 1 1]>.
L<reference> or L<description|reference>
Создает ссылку на существующий reference. Если часть
description опущена, то видимым текстом ссылки будет reference, в
противном случае это будет description. Команда L
отдаленно
напоминает гиперссылку HTML <a
href="reference">description</a>, но в POD
reference не является унифицированным локатором ресурса (URL).
reference может ссылаться только на сгенерированные метки [labels],
которые автоматически создаются трансляторами POD-во-что-то-другое. Такие метки
создаются для каждой команды =head
и =item
. Метка,
связанная с командой =head
heading будет образована из
переведенного в нижний регистр heading, других изменений в
heading не делается. А именно, заголовку:
=head1 Заголовок из Нескольких Слов (ЗНС)
будет автоматически сопоставлена метка
заголовок из нескольких слов (знс)
К меткам для =item
'ов добавляется префикс item_
,
пробелы заменяются символами подчеркивания, а не-буквы и не-цифры заменяются на
знак процента, за которым следует их шестнадцатеричный ASCII-код. А вы ожидали
преобразования попроще? Так, если бы при подготовке данной статьи один из
пунктов был бы обозначен, как
=item Автоматическая Генерация Ссылок.
то он получил бы метку
item_Автоматическая_Генерация_Ссылок%2e
поскольку ASCII-код точки равен 46 или 2e в шестнадцатеричном формате.
Пример:
Исходный текст
=head1 Введение В разделе L<"Концепции"> излагаются основы. =head1 Концепции ... =head1 Синхронизация =over 4 =item Блокировки =item Race Conditions =item Разрешение блокировок =back То, как справляться с блокировками уже обсуждалось в L<разделе Блокировки|"item_Блокировки"> и L<Разрешение блокировок|"item_Разрешение_блокировок">.
Результат
В разделе Концепции излагаются основы.
...
То, как справляться с блокировками уже обсуждалось в разделе Блокировки и Разрешение блокировок.
Использование команды L
сильно ограничено тем, что пишущий не
может помечать места, на которые будет можно сослаться в дальнейшем в командах
L
: команды, подобной "acnhor" в HTML нет.
Вторым ограничением является то, что некоторые POD-трансляторы пытаются умничать и "украшают" ссылки дополнительным текстом. Например, pod2latex в примере ниже преобразует обе ссылки на пункты списка:
Как справляться с блокировками обсуждалось в разделе, обозначенном как \textsf{Блокировки$|$"item\_Блокировки"} в другом месте этого документа, и в разделе, обозначенном как \textsf{Разрешение блокировок$|$"item\_Разрешение\_блокировок"} в другом месте этого документа.
Примечание переводчика: Переводя эту статью, я проделал несколько экспериментов с целью уточнить, как описанные приемы работают в кириллическом окружении. Так вот, у меня на компьютере pod2latex фрагмент приведенного выше примера превратил в следующий текст << То, как справляться с блокировками уже обсуждалось в L<разделе Блокировки$|$"item\underscore{}Блокировки"> и L<Разрешение блокировок$|$"item\underscore{}Разрешение\underscore{}блокировок">. >>. Т.е., совсем странно, я даже не стал пробовать, как это будет в dvi:( Поэтому я привожу ниже тот же параграф по-английски, для того, чтобы можно было легче понять мысль автора:). pod2html, впрочем, отработал на примере нормально (или почти нормально). А вот pod2text "сумничал": << Как справляться с блокировками обсуждалось в разделе the section Блокировки... >>
How to cope with deadlocks was discussed in the \textsf{Deadlocks$|$"item\_Deadlocks"} entry elsewhere in this document, and the \textsf{Recovering from Deadlocks$|$"item\_Recovering\_from\_Deadlocks"} entry elsewhere in this document.
подчеркнутые слова добавлены pod2latex. Ясно, что нам нужен способ получше. Этот лучший способ осуществляется с помощью формато-специфичных абзацев.
Мы только что увидели, что командой L
не так-то легко управлять.
А почему мы не можем просто использовать HTML-ссылку? Краткий ответ "потому что
POD -- это не HTML" подсказывает решение. Если бы мы могли указать, что этот
абзац предназначен для HTML, этот -- для LaTeX, а этот -- для SnaFoo", то мы
могли бы использовать разметку, специфичную для этих форматов.
Специальная команда
=for
format абзац_текста
указывает транслятору обратить внимание на format перед тем, как он
станет обрабатывать абзац_текста. Если транслятор чувствует, что он
"отвечает" за обработку формата format, то он его обрабатывает по своим
правилам, в противном случае он его полностью игнорирует. Вторая часть названия
обработчика обычно указывает, в какой формат он транслирует. Например
pod2man работает с =for man
, pod2html преобразует
абзацы =for html
, и т.д.
Всякий раз при использовании формато-специфичного абзаца в документе
появляется "ветвление" (поскольку разделы =for
format
должны быть созданы для каждого из предполагаемых выходных форматов), тем самым
пробивается брешь в стройной структуре документа.
Это обычный абзац, который обрабатывается всеми трансляторами. =for html <p>Этот абзац появится только в файле обработанном <b>pod2html</b>.</p> =for latex Тот же самый абзац, но оттранслированный {\bf pod2latex}. =for text А я предназначен для *pod2text*. Продолжаем писать для всех и всяких форматов.
Трансляторы игнорируют неизвестные форматы, так что мы можем изобрести абзацы для своих специальных нужд! Например, чтобы закомментировать сразу целый абзац, можно написать:
=for comment Кто-нибудь может разобраться со следующим разделом?
Часто используется формат emacs
:-) Для того чтобы при
подготовке POD-файла переключить emacs в текстовой режим,
начните файл с:
=for emacs -*- text -*-
или закончите его так:
=for emacs Local Variables: mode: text End:
Те пользователи emacs, которые применяют дополнение hyperbole, могут превратить имеющиеся у них "тупые" POD-файлы в связанную гипрессылками коллекцию (на самом деле возможности hyperbole этим не исчерпываются, но гиперссылки -- хорошее начало) файлов следующей командой:
=for hyperbole <(std-reference)>
где <(std-reference)>
-- это кнопка hyperbole, которая,
стоит по ней кликнуть мышью, переносит вас в другой файл, содержащий
документацию по std
.
Преобразуют текст из формата POD в соответственно HTML, страницы руководства UN*X (man pages), LaTeX и обычный текст.
Простое средство проверки синтаксиса POD.
Страницы man для perlpod(1), pod2man(1), pod2html(1), pod2latex(1), pod2text(1) и podchecker(1).
В следующем месяце: LaTeX в связи с latex2html.
Крис руководит расположенной в Верхней Баварии (Германия) компанией, консультирующей по вопросам Open Source Software. Не смотря на то, что по образованию он физик (он получил ученую степень Доктора Философии в Мюнхенском Технологическом Университете), его главные интересы вращаются вокруг численных методов, гетерогенных сред программирования и разработки программного обеспечения. Связаться с ним можно по адресу [email protected].
Команда переводчиков:
Владимир Меренков, Александр Михайлов, Иван
Песин, Сергей Скороходов, Александр Саввин, Роман Шумихин
Со всеми предложениями, идеями и комментариями обращайтесь к Сергею
Скороходову ([email protected])
Сайт рассылки:
http://gazette.linux.ru.net