Elaborate Command

Most UNIX commands have flags, arguments, return values, environmental variables, and so on. So let's expand upon our example to include arguments for writing to an output file and a flag for outputting in uppercase letters. Furthermore, we'll accept an optional prefix string on the command-line, and return non-zero on failure.

This changes two parts of our manual: the SYNOPSIS section, where we'll record the invocation syntax of our command; and the DESCRIPTION, where we'll describe the command-line options. We'll also add a new section, EXIT STATUS, to describe the non-zero exit on failure.

Let's start by documenting our command-line options in the SYNOPSIS section:

.Sh SYNOPSIS
.Nm
.Op Fl C
.Op Fl o Ar output
.Op Ar prefix

The output renders as follows:

SYNOPSIS

hello [-C] [-o output] [prefix]

Already, we begin to see the output take shape with the C and o characters, and the prefix. It's also clear that the Op macro surrounds its arguments in square brackets, just as Qq surrounded its line in double-quotes.

But how did the formatter know to prefix the C and o with a dash, or underline the arguments output and prefix?

It's obvious this has something to do with Fl and Ar.

Macro lines may in fact consist of multiple macros — sometimes nesting further macros, sometimes closing prior scopes to begin one anew. The Fl and Ar words are macros nested within the scope of Op. However, while Op contains both of these child scopes, the Ar macro closes out the Fl scope and begin its own.

.Op Fl C
.Op Fl o Ar output
.Op Ar prefix

Outer parts are an outer scope, while inner parts are an inner scope. Now it's easy to see how Fl prefixes only the C with a dash and not the arguments following: its scope is closed out by Ar.

Note that to document a flag Ar, we would need to quote its arguments as Fl "Ar" (we'll later learn how to escape arguments with zero-width spaces to accomplish the same). As there are many mdoc macros, a popular novice mistake is to unknowingly invoke a macro when expecting to print text.

With our command syntax documented, let's document the arguments themselves. To do so, we detail the meaning of flags and arguments in the DESCRIPTION section.

The
.Nm
function prints
.Qq hello, world
and returns.
.Pp
Its arguments are as follows:
.Bl -tag -width Ds
.It Fl C
Print only uppercase letters.
.It Fl o Ar output
Write to file
.Ar output .
.It Ar prefix
Prefix the output with
.Ar prefix .
.El

Immediately, we see the introduction of several new macros: Pp, Bl, It, and El. More interestingly, we notice the text on the Bl begins with a dash, just as when passing arguments on a command line. This is the first instance of a macro that accepts flags.

The rendered output of this fragment is as follows.

Its arguments are as follows:
-C
Print only uppercase letters.
-o output
Write to file output.
prefix
Prefix the output with prefix.

It should be clear that the Pp macro, which always stands alone, introduces a vertical paragraph break.

Earlier, I introduced the concept of a multi-line scope for Sh, which was closed and re-opened by subsequent invocations of Sh. In this fragment, the Bl macro (for begin list) is explicitly closed out by the El macro (end list). This is an example of explicit scope closure, versus the implicit scope closure of Sh sequences.

Predictably, the Bl and El enclosure consists of list items, begun by the multi-line It macro lines. Like Sh, the It macro has its scope closed by subsequent invocations of It. As expected, its scope also closes when the surrounding list is closed with El.

Until now, we've discussed only macros and macro arguments. But a handful of macros — Bl included — also accept flags which themselves may have arguments. In our example, the tag flag to Bl stipulates a tagged list. A tagged list entry consists of two parts: a tag and data, similar to the <DL> descriptive lists in HTML consisting of a key and data. Bl accepts a second flag, width, which accepts the argument Ds. This instructs the formatter that the tag portion of the list has width Ds, which is shorthand for default spacing.

Next, let's look closer at the input line

.Ar prefix .

Note that it's correctly rendered with the period flushed up against the text, whereas the period is space-separated in the input. (The period itself isn't font-decorated, although this is difficult to see in the media you're reading.)

prefix
Prefix the output with prefix.

By making the punctuation a separate argument, we distinguish it from the term prefix, and thus it is not underlined. The formatter is smart enough to distinguish standalone punctuation. When writing an mdoc manual, punctuation should always be separated from macro arguments unless it's part of the argument itself. This allows the formatter to correctly intuit end-of-line spacing.

If we hadn't done so, the formatter wouldn't distinguish period from word. This is more intuitive when re-using the familiar Qq.

.Qq first .
.Qq second.

We can now see the difference in the placement of punctuation:

first”. “second.

Let's piece this all together. You'll recognise the Dd, Dt, and Os macros from the last section, although the Dt argument has changed with our command name.

.Dd May 30, 2011
.Dt HELLO 1
.Os
.Sh NAME
.Nm hello
.Nd print \(dqhello, world\(dq
.Sh SYNOPSIS
.Nm
.Op Fl C
.Op Fl o Ar output
.Op Ar prefix
.Sh DESCRIPTION
The
.Nm
function prints
.Qq hello, world
and returns.
.Pp
Its arguments are as follows:
.Bl -tag -width Ds
.It Fl C
Print only uppercase letters.
.It Fl o Ar output
Write to file
.Ar output .
.It Ar prefix
Prefix the output with
.Ar prefix .
.El

Notice that we don't repeat the Op macros in the DESCRIPTION, although we stipulate them in the SYNOPSIS. This is because we document the flags and arguments themselves in the DESCRIPTION, not the calling syntax of the command.

Finally, let's accomodate for command errors by stipulating the exit status of the command. To do this, we add a new section to the end of the manual, EXIT STATUS, consisting of a single macro. We didn't add this to hi.1 because we didn't stipulate any exit state; however, it's good practise to always include this section, even if your command only exits in one way.

.Sh EXIT STATUS
.Ex -std

The Ex macro is special in that it always accepts a flag, std. This is by convention. Although you can specify an argument to Ex, it works like Nm without arguments in that it reproduces the name of the document as last invoked with Nm. It prints a standardised message about the exit status of the command.

EXIT STATUS

The hello utility exits 0 on success, and >0 if an error occurs.

With our manual complete, let's go over our checklist.

Did I describe the calling syntax of the command?
Yes, including flags and arguments.
Did I describe each flag and argument of the command?
Yes for all flags and arguments.
Did I describe the command's operation?
Yes, that it prints hello, world.
Did I describe the command's exit status?
Yes, that it returns a non-zero exit code on failure.
Did I describe referenced files and environment variables?
This is not applicable to this manual.

Of course, most real manuals have many other useful bits of information, such as author names, referenced standards, files, and so on. I'll describe these in detail in later chapters of this book.

Last edited by $Author: kristaps $ on $Date: 2011/11/04 22:57:49 $. Copyright © 2011, Kristaps Dzonsons. CC BY-SA.