[home] [software] [knowledge base] [manpages] [code] [markdown] [my ip]

Пишем UNIX мануалы

Ранее для написания мануалов я пытался применять Markdown и reStructuredText, но как оказалось docutils генерирует не совсем верную разметку и полученную страницу нельзя корректно перегнать в другие форматы.

Пришлось писать мануал прямо в формате man, что оказалось не так страшно как выглядело.

С названиями может возникнуть путаница (я запутался), но вот что есть что:

  • roff -- первый текстовый процессор для UNIX;

  • nroff, troff -- следующая итерация roff для UNIX;

  • ditroff -- поздняя версия troff для UNIX от Б. Кернигана;

  • groff -- замена nroff и ditroff от проекта GNU;

  • mandoc -- замена groff в *BSD.

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

Далее речь пойдёт о groff. Стайлгайд и общие положения по написанию мануалов можно найти в man-pages(7).

Настоятельно рекомендую посмотреть страницу groff_man(7) с описанием синтаксиса, это будет отличным дополнением к существующей заметке. Для полного погружения также можно полистать документацию groff.

Заголовки

Заголовок страницы

.TH FREE 1 "2018-05-31" "procps-ng" "User Commands"

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

Поля по порядку:

  • Название страницы. Обычно совпадает с именем программы. Традиционно пишется в верхнем регистре.

  • Номер раздела мануалов.

  • Дата последнего изменения страницы мануала.

  • Источник. Сюда пишут имя пакета в составе которого поставляется утилита. Здесь это пакет procps-ng. Так в мануале ls указано GNU coreutils 9.1.

  • Текстовая расшифровка раздела мануалов. Поле можно опустить, тогда man сам покажет описание раздела, например, General Commands Manual для 1-го раздела и т.д.

Заголовок первого уровня

.SH NAME

Заголовок второго уровня

.SS Something

Встрочная разметка

В мануалах обычно используются только жирный и курсивный текст. Последний при просмотре через man отображается как подчёркнутый текст.

В примере ниже весь текст на текущей строке будет жирным или курсивным.

.B Жирный текст
.I Курсивный текст

В следующем примере первое слово будет отформатировано, затем форматтер будет сброшен (R) и далее последует обычный текст.

.BR Жирный_текст обычный текст
.IR Курсивный_текст обычный текст

Можно, конечно, вставить отформатированный текст в середину строки.

Здесь \fBжирный\fR и \fIкурсивный\fR текст в одном абзаце.

Думаю, логика понятна.

Абзацы и отступы

Абзац можно получить отступив пустую строку, но это не рекомендуется. Лучше использовать макросы .PP или .IP для абзаца с отступом.

С помощью .TP можно получить абзац с отступом и лейблом. В HTML это будет представлено как defenition list. Крайне полезно для описания опций программы или определений.

Ниже фрагмент страницы для утилиты free.

.TP
\fB\-b\fR, \fB\-\-bytes\fR
Display the amount of memory in bytes.
.TP
\fB\-k\fR, \fB\-\-kibi\fR
Display the amount of memory in kibibytes.  This is the default.
.TP
\fB\-m\fR, \fB\-\-mebi\fR
Display the amount of memory in mebibytes.

Да, минусы нужно экранировать в тексте.

Очень не хочется пересказывать groff_man(7), так что смотрите сами:

Таблицы

Таблицы это целая наука, есть довольно наглядное видео на тему. За работу с таблицами в groff отвечает процессор tbl.

Вот простая таблица:

.TS
allbox;
l l l.
Таблицы     это     круто
foo         bar     foobar
.TE

Здесь allbox это опция, которая включает отображение границ ячеек. l l l. означает, что далее последует таблица из трёх столбцов с выравниванием по левому краю. Для выравнивания по центру l надо заменить на c. После определения столбцов следуют сами данные. Замечу, что по умолчанию разделителем столбцов является символ табуляции.

Пример страницы

.\" vim: set filetype=groff:
.TH FOO 1 "2022-01-10" "foo 0.1"
.SH NAME
foo - do something.

.SH SYNOPSYS
.SY foo
.OP \-\-help
.OP \-\-version
.OP \-\-config file
.YS

.SH DESCRIPTION
.PP
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
.PP
Condimentum vitae sapien pellentesque habitant morbi. Ipsum nunc aliquet
bibendum enim facilisis gravida neque convallis.

.SH OPTIONS
.TP
.B \-\-help
Print help message and exit.
.TP
.B \-\-version
Print version and exit.
.TP
\fB\-\-config\fR \fIfile\fR
Configuration file.

.SH FILES
.TP
/etc/foo.conf
foo configuration file.

.SH SEE ALSO
.BR foo.conf (5),
.BR bar (1)

Экспорт страницы

groff умеет рендерить мануалы в PDF (через gropdf) и HTML. PDF получается особенно красивый.

groff -man -Tpdf foo.1 > foo.1.pdf

Если в мануале используются таблицы, то сперва файл надо пропустить через tbl.

tbl -T pdf foo.1 | groff -man -Tpdf > foo.1.pdf

Получить нормальную таблицу в HTML у меня не получилось. Groff генерирует пустую картинку вместо неё.

groff -man -Thtml foo.1 > foo.1.html

mandoc(1) рендерит более удобоваримый HTML и отлично справляется с таблицами, однако, не может корректно обработать макрос .SY (Command synopsis macros) -- показывает только опции команды.

mandoc -Thtml foo.1 > foo.1.html