Writing man pages


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 <b>, <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); and .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, .B and .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 (\) character.

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.

The header

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 <xxx@yyy.zzz> for corrections .TH "BASIC-MANPAGE" 7 "2017-11-25" "" "Miscellaneous Information Manual"

It is common to start a man page with a comment (a .\" or '\" 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:


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 .SS macro.

.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:

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

The .SY and .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 .OP macro; 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 -d option that's expecting one.

For other stuff, like mandatory switches or arguments, you can just type some freehand text.

Describing options

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.

Style guide

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 man-pages(7) are:


Share with friends

e-mail Google+ Hacker News LinkedIn Reddit Tumblr VKontakte Wykop


Do you have some interesting thoughts to share? You can comment by sending an e-mail to blog-comments@svgames.pl.