Writing man pages2017-11-26
One of the aspects of Unices that I personally very much enjoy is the concept of the system manual – with just a single command in the terminal, you can get a nice description of most available programs (applies also to C functions and a lot of other stuff). It should be no wonder that I tend to get slightly annoyed when I install a new package and find out that the authors didn't bother to write a man page (and neither did the packager). As such, when writing software myself, I ensure to include a man page to save other people from similar annoyances.
Before we start
Man pages are written using the roff markup language. If you've never heard of roff before, that' mostly because as far as I know, man pages are basically the only significant place left that still uses roff. Historically, roff has been used for preparing documents and typesetting (indeed, there have been entire books written using roff), but nowadays it has been mostly chewed out by LaTeX and WYSIWYG editors.
For those of you familiar with LaTeX, roff may be slightly reminiscent, since it also follows a
"raw text interspersed with formatting marks" philosophy. (Arguably, the same could be said of
old HTML, with its
<i> and other styling tags.)
As troff.org nicely puts it, it's
basically a "What you describe is what you get" approach to typesetting.
Similarly to LaTeX, roff can be extended with new macros. Indeed, when writing man pages, we're going to use some macros that are not standard roff, but additional macros created for said purpose.
Basic text formatting
As stated earlier, in roff, we use formatting marks to describe how our text should look like.
The fundamental type of formatting marks are requests, which must be placed at the beginning
of a line, and start with a dot (
.) or an apostrophe (
This is a very simple example of how to use .I requests when using .B roff to write man pages. As you can see, linebreaks in the input are ignored when displaying the document. To start a new paragraph, simply leave a blank line. .br The ".br" request can be used if you need to perform a linebreak.
In the above example, we use three requests: the
.br request, which performs a linebreak;
.B, which makes all the text following it, until the end of the line, to be written with a
bold font (alternatively, the request can appear alone,
in which case the font change will apply to text in the next line);
.I, which works similarly, but makes the text be displayed with an underline.
Or rather – it switches to an italic font, but since terminal displays don't support that,
man displays underlined text instead.
Also, should we want to be technically correct,
.I aren't requests,
but rather macros which expand to proper requests. They are defined by man, and, as such,
are not "standard" roff. Though that's a bit like saying that
my_function() is not standard C.
Either way, apart from requests, we can also use escape sequences, which, contrary to requests,
are inline elements. Similarly to many programming languages, escape sequences
begin with the backslash (
This is an example of how to use \fIescape sequences\fR when writing \fBroff\fR documents.
Both requests and escape sequences are powerful mechanisms that allow us to do things like control fonts, define and output constants and variables, include other files, perform conditional output – or even output in a loop! Although for writing man pages, we probably won't need most of those features.
Now that we have some rudimentary understanding of how writing in roff works, let's begin by taking a look at the man page header.
.\" Man page by asdf, contact <email@example.com> for corrections .TH "BASIC-MANPAGE" 7 "2017-11-25" "" "Miscellaneous Information Manual"
It is common to start a man page with a comment (a
'\" request) describing the document
author and means of contact for reporting mistakes and such. The printable content should
start with the
.TH command, which performs the role of the man page header.
As you can see, this macro takes five arguments:
The name of the document, usually matching the name of the program or function being described. The convention says this should be written in all uppercase.
The manual section. There are eight basic sections, with some man pages belonging to subsections; a good example of this is section 3p, which commonly holds man pages for functions as defined by POSIX, whereas section 3 itself holds man pages for the versions available on your system (which may differ from POSIX in their behaviour). The
man-pages(7)document describes them as such:
User commands – commands that can be executed by the user from within a shell.
System calls – functions which wrap operations performed by the kernel.
Library calls – all library functions (excluding the system call wrappers).
Special files (devices) – files found in
/devwhich allow to access to devices through the kernel.
File formats and configuration files – descriptions of various human-readable file formats and configuration files.
Games – games and funny little programs available on the system.
Overview, conventions, and miscellaneous – overviews or descriptions of various topics, conventions and protocols, character set standards, the standard filesystem layout, and miscellaneous other things.
- System management commands – commands like
mount(8), many of which only root can execute.
The document's modification date. This should reflect the last time any nontrivial changes were made, so you can leave the date be if all you're doing is just fixing formatting and typos, without really changing the text. The convention says the date should be written in ISO8601 format (
The source of the program or function. For man pages describing library functions, or programs which are part of a larger package, you might want to scribble the name of the collective work here; otherwise, use
""to specify an empty string.
- The title of the manual. While this could probably be guessed from the section number, the convention is to write it here either way.
Man pages usually consist of several sections. These are marked using the
.SH section header macro.
Should you need to define a subsection, use the
.SH NAME \fBbasic\-manpage\fR \- a very simple man page .SH DESCRIPTION .SS Purpose This is a very simple man page meant to demonstrate the basic structure of the document. .SS Other parts This man page is divided into several parts for easier reading; you'll have to paste them together to get an actual document.
By convention, section names are written in all uppercase. Some common sections are:
NAME – shows the name of the document along with a very short summary.
SYNOPSIS – for programs, displays a template of how to invocate it. For functions, shows the return type and the parameters.
DESCRIPTION – a longer, more detailed description of the subject of the man page.
OPTIONS – for programs, lists the available command line options. It is highly preferable that you don't limit this list to the most commonly used options, but rather write all of them. If there's truly a lot of those, use the subsection feature to group them.
FILES – mentions files used by programs, e.g. where do they store their configuration files and other data.
NOTES – miscellaneous remarks that may be useful to users.
EXAMPLE – for complicated programs (or ones that take a plethora of options), you may include some usage examples so the users feel less intimidated.
- SEE ALSO – a place to list related man pages; this list should be ordered by section first, and by name second. You can also put URLs to on-line resources here.
Writing a synopsis
As stated before, the synopsis demonstrates how to launch the program. While we may write this as a normal paragraph, just using escape sequences to properly embolden/italicize the font, there are a couple convenience macros available that we can use to help us write the synopsis. A benefit of using these macros is that all the text following the program name (or whatever else we're describing), should it not fit on a single line, will be indented past the name, giving it all a nice look. Using these macros also helps automatic tools in processing the man page.
.SH SYNOPSIS .SY hello\-world .OP \-a .OP \-d DIRECTORY [\fIFILE\fR]... .YS .SY hello\-world \fB\-\-help\fR | \fB\-\-version\fR .YS
.YS macros mark the beginning and the end of the synopsis, respectively.
You can include multiple synopses by using the
.SY macro several types; when doing so, using
.YS between synopses is optional – doing so will insert a blank line between the
demonstrations, while omitting it will make them appear one right under the other.
To describe program options and their arguments, use the
it takes two arguments, the first being the option name, and the second being its argument.
In the example above, we have an
-a option that doesn't take an argument, and a
that's expecting one.
For other stuff, like mandatory switches or arguments, you can just type some freehand text.
Probably the most common reason people fire up
man is to check the options which
a program may accept. As such, it's important to describe these as accurately and
thoroughly as reasonably possible.
.SH OPTIONS .TP .B \-s This is a paragraph describing a short option. .TP \fB\-\-nuke\fR \fIFILE\fR This is a paragraph describing a long option. This option takes a single parameter, \fIFILE\fR. .TP .B \-\-only-odd .TQ .B \-\-only-even This is a paragraph describing both of the above long options. Because these options affect the way the program works in a significant way, we made a second paragraph describing them. .PP This is an additional paragraph that doesn't describe any options, but instead provides some informational text.
In the above snippet, I use the
.TP macro, which introduces an indented paragraph with a label.
The label goes on the next line following the macro; any text after that is treated as belonging
to the indented paragraph. For describing options, write the option itself as the label, and
then put the description into the indented paragraph. If you want to have multiple labels
(for example, we have two complementary options that can be described together),
you can use the
.TQ macro for this purpose.
While describing options, it is common to write options with a bold font, and their arguments with an italic (underlined) font. This should also apply to repetitions of these names within any description paragraphs.
Descriptions themselves can be multi-paragraph; just leave a blank line, as usual.
If you feel that you need to put any additional text after describing the options,
you can use the
.PP macro to reset the indentation.
As with any other type of content that's written by many authors, personal preferences on how to write man pages can result in very different files delivering the same text. And like in every programming language, there is a style guide that provides a set of rules which can be used to ensure our documents are easily readable.
Some of the rules mentioned by
Gender neutral language – as far as possible within the spoken language you're writing the man page in, use gender neutral language. For English, this means using "they" when referring to an actor (e.g. "should a user want to do X, they can use option Y").
Embolden the page name – when describing a program or a function, all occurences of the subject name in the text should appear in a bold font. For functions, the name should be followed by a (non-bold!) pair of parentheses.
\-for minuses/dashes – one thing you might have noticed in the examples above was the common usage of an escaped dash (
\-). This is because a roff renderer can choose to display a "lone" dash using some kind of Unicode glyph; escaping the dash ensures we get the proper character. Remember that, while we're mostly focusing on viewing our page in the terminal, the roff source can also be rendered to a document format like HTML or PDF.
Where applicable, use
\ for non-breaking spaces.
- Where applicable, use the
\%escape sequence to prevent a word from being hyphenated.