Blind Dog Software
Home | Goodies | About

Not Your Father's Man Pages

This information was presented to Seattle Xcoder's Eastside meeting on 4/27/2017 as a 15-minute "Lightning Talk."

As we move from viewing "standard" manual pages in a Unix terminal (not Mac-like) to viewing them in a much more readable Mac application—in this case, Preview.app—I'll highlight various Unix concepts and issues along the way.

Unix Man Pages

Unix comes with a rather large body of online manual pages which are accessed from a Unix terminal window via the command man. Hence the common name, "man pages," short for manual pages. Man pages have a common format describing all, or nearly all aspected of the topic of the page. Some man pages are highly focused on a given command whereas others are far more general, and can be quite long. Furthermore, man pages are organized by "section," where certain kinds of information about a topic are found in the general section.

The place to start learning about the features of man and how to use it is to open Terminal.app and enter:

man man
at the prompt. Your prompt will disappear and the screen will be filled with the manual page. At this point, you will interact with the manual page viewer in ways that directly depend upon which man page viewer is employed. By default, man man is the same as entering man 1 man where 1 is the most general, introductory section for a topic. Pay attention to the ordering: man 3 printf will give you a manual page about the Unix C library function printf whereas man printf 3 will ignore the 3rd parameter and just give you the section 1 manual page for printf.

Here, how you navigate the manual page will depend upon how man is configured to use one of many possible ways to view the manual pages. The viewers can be wildly different and sometimes behave in unexpected ways if you mistake one for another. We'll cover a few of them here; we will not cover all of them.

By default, man formats and opens the manual page contents with a text viewer called less. In the very beginning, there was cat which simply concatenated, or wrote out, a file to the screen. The whole man page just spilled out onto your screen without stopping; no paging, no up or down scrolling—not terribly convenient. As Unix matured, a better solution came along. This was more which spilled out the contents of the man page a page or screen at a time. Far better than cat but it did not allow for backward scrolling of the pages. Finally, more was replaced by less. Less allows both forward- and backward-movement within the file as it is displayed.

Slightly better.

But after years of reading proportionally spaced fonts, I find reading fixed-witdth fonts rather difficult and unnatural. Add to that the fact that manual pages are written as if you already know Unix generally; they are not written for the total neophyte. Consequently, man pages can be very cumbersome to read let alone understand. Hence, the desire to view them in a GUI app instead of in a Terminal window. When both the presentation of content and navigation through that content are much more familiar, focus upon and understanding of the content is facilitated. To be honest, since I've been using Preview.app for man pages, I've found them much more enjoyable and informative read. Others may prefer reading man pages in vi or emacs text editors. It really depends on what you are most comfortable with and what best compliments your workflow.

Other man Tidbits

After you finish configuring man the way you like, you may want to explore these topics:

Also, be aware that Unix has many, many variations. Not all man pages contain the same information. For instance, the man page for man sometimes contains a description of each section; the macOS version does not. In other words, they are system dependent and can sometimes be wildly out of date.

Unix pipes

One of the most powerful features of Unix is the "pipe." This is the ability to take the output of one program and use it as input, or "pipe it," to another program. In this manner, one can construct a complex sequence of file manipulations that would be difficult and cumbersome to achieve otherwise. This is facilitated by the existence in 3 standard Unix data streams available to all Unix programs:

In bash, as well as every other Unix shell, the pipe command is represented by "|".

Back to man

Before more, less, and the enhanced ability to format man pages we have today, it was common to use pipes to format a man page to plain text, saving it to a file. This could then be opened with your favorite Unix text editor:

man 7 intro | col -bx > intro7_man.txt
Here, the > symbol is a file redirector telling the output of col piped to the file system as input for the file intro7_man.txt. Then the file can be opened and read with a text editor, in this case vi:
vi intro7_man.txt

Still cumbersome, even if you opened that file with Preview because col -bx strips out most formatting characters.

One remedy for this sad state of affairs is the environment variable MANPAGER. When this environment variable is absent, the default behavior would be as if one entered:

man 7 intro | /usr/bin/less -is
and we're back to less. To set this explicitly, you would add:
export MANPAGER="/usr/bin/less -is"
to your .bash_profile file in your home directory (more on that in a bit).

If you prefer to use vi or vim (they are the same on macOS), you could set MANPAGER to:

export MANPAGER=/bin/sh -c \"col -b | vim -c 'set ft=man ts=8 sw=4 nomod nolist nonu noma' -\""
This runs a new shell (within your existing one) with the command string between " and " as if you typed it into the command shell yourself. The specified command takes the output of man and pipes it into col to remove formatting. It then pipes that output to the vim editor with a set of parameters to enable read-only viewing in vim. When you quit vim, the shell exits, returning you to the shell where you issued the man command.

Spiffy, but still, "so last century!"

From Unix terminal to Preview.app

Returning to the man page for man, we find there is a parameter -t that formats a manual page for .PDF output which can then be further passed to groff for further processing. We would then enter

man -t printf
Furthermore the man page states the -t option calls /usr/bin/groff -Tps -mandoc -c where -Tps says format the output for Postscript, -mandoc says to expect mandoc format as input and -c says not to use color specifications in the output stream.

While the man page states man -t printf calls /usr/bin/groff -Tps -mandoc -c, it implies using one was the same as using the other. But they are not the same. Let's see for ourselves.

If you set

export MANPAGER="/usr/bin/groff -Tps -mandoc c"
you will find that you don't get bolding, underlining, paging, etc. and it's not quite right where letters in headings overlap and not really readable. To fix that, you'd have to set
export MANPAGER="col -bx | /usr/bin/groff -Tps -mandoc c"
where col strips out the formatting to get readable output. Okay, but without the nice formatting we're really looking for. "Close, but no cigar," as the man at the circus used to say.

Turning to the man source code, available here https://opensource.apple.com/source/man/man-16/ (you have to root around a bit to figure out what's actually being done), you will eventually find that in man.c, the rountine make_nroff_command function is prepending and appending specific Postscript page and line commands to the output stream it sends to groff. <gak!> So we're back to man -t.

What macOS app reads PDF?

Preview.app, of course. But how do we get Preview to read stdout from another program as stdin for its input?

For this we turn to the open command. You may want to do a man open at this point to see for yourself what is available there. By the way, open is very useful when going from your directory location in a terminal window to a Finder window. Simply enter open . and the Finder opens a window at that directory location.

With this knowledge, we can now use the command line

man -t man | open -f -a Preview.app
and our beloved man man page opens beautifully formatted in Preview.

The last part of this journey is to be able to use the MANPAGER environment variable to do the same thing. How do you get the command parameters to MANPAGER?

The answer is to pass the command parameters along. You do this with "$@", thusly:

export MANPAGER="man -t "$@" | open -f -a Preview.app"

The Finish Line

Finally, to make this a part of your command shell, two lines need to be added to your .bash_profile.

  1. function preview_man () { man -t $@ | open -f -a Preview.app; }
  2. alias pm = preview_man
pm will be your new command alias to execute the function preview_man.

Here are the steps to do this:

  1. cd ~ or cd $HOME to get to hour home directory.
  2. vim .bash_profile to open or create that file (it may not exist).
  3. Add the function and alias lines, given above, to that file.
    (You'll have to know a bit of vim, so perhaps do a man vim before beginning the edit session—or—once in vim enter :h to enter its help and :q to exit its help.)
  4. :wq in vim to save and quit it.
  5. Close your terminal window, and open a new one; this will read in the new .bash_profile settings.
  6. Enter pm man or pm intro instead of using man.

Badda–Bing! Badda–Boom! ... Not your father's man pages!


Copyright © 2017 Blind Dog Software. All Rights Reserved.