Pipe man into col -b to get rid of ^H

The man page reading club is returning soon. In the meantime, here is a short post on a trick related to man itself that I skipped in the first post of the series.

Vi rocks

A cool feature of vi-like editors is that you can insert the output a command in the file you are editing, without doing any awkard copy-pasting. You can do this with the r ex command:

:r !date

Inserts the output of the date command on a new line. You can also use the ! (bang) command, combined with a motion, to feed the text between the cursor and the target of the motion to a command and replace it with the output of the command itself. For example I often use !}fmt to format the next paragraph when I am writing an email.

Man pages and ANSI escape codes

Unfortunately, if you try to use this feature to include parts of a man page, you might not like the result. Typing :r !man man | head gives

MAN(1)                      General Commands Manual                     MAN(1)

N^HNA^HAM^HME^HE
     m^Hma^Han^Hn - display manual pages

S^HSY^HYN^HNO^HOP^HPS^HSI^HIS^HS
     m^Hma^Han^Hn [-^H-a^Hac^Hcf^Hfh^Hhk^Hkl^Hlw^Hw] [-^H-C^HC _^Hf_^Hi_^Hl_^He] [-^H-M^HM _^Hp_^Ha_^Ht_^Hh] [-^H-m^Hm _^Hp_^Ha_^Ht_^Hh] [-^H-S^HS _^Hs_^Hu_^Hb_^Hs_^He_^Hc_^Ht_^Hi_^Ho_^Hn]
         [[-^H-s^Hs] _^Hs_^He_^Hc_^Ht_^Hi_^Ho_^Hn] _^Hn_^Ha_^Hm_^He _^H._^H._^H.

D^HDE^HES^HSC^HCR^HRI^HIP^HPT^HTI^HIO^HON^HN

Not cool! This happens because manual pages are not made of plain text. They contain ANSI escape codes to provide some basic formatting, like bold text and whatnot (you might or might not see them, depending on the capabilities of your terminal emulator). This is a complex topic and I don’t know much about it. Check out the excellent post Anatomy of a Terminal Emulator by poor.dev if you want to learn more.

Long story short, the workaround is included in the man page itself:

When using -c, most terminal devices are unable to show the
markup.  To print the output of man to the terminal with markup
but without using a pager, pipe it to ul(1).  To remove the
markup, pipe the output to col(1) -b instead.

Indeed, using :r !man man | col -b | head gives:

MAN(1)              General Commands Manual         MAN(1)

NAME
     man - display manual pages

SYNOPSIS
     man [-acfhklw] [-C file] [-M path] [-m path] [-S subsection]
     [[-s] section] name ...

DESCRIPTION

Hooray!