#!/bin/sh
file="${1:-README.md}";

if [ -f "$file" ]; then
  pandoc -s -M header="$(basename "$file")" -f gfm -t man "$file" | man -l -
else
  echo "File could not be found."
fi

The code above transforms a markdown file into a manpage for easy reading in the terminal. Although markdown in itself is already readable in its pure raw format, this makes it even nicer.

As you can see Pandoc is doing all the work here, it is the tool converting the markdown into a manpage. Let’s go over the basic flags we gave it:

  • -s asks for a “standalone” document,
  • -f gfm tells Pandoc we want to convert from Github flavoured markdown (gfm) and
  • -t man indicated that we want to get out a manpage.

There is one flag we did not discuss yet: -M header=.... This flag sets the value of the metadata field header to the filename of the file we are looking at. If we look at Pandocs default template for manpages, we see that the metadata field $header is used in the line starting with .TH.

.TH "$title/nowrap$" "$section/nowrap$" "$date/nowrap$" "$footer/nowrap$" "$header/nowrap$"

From the man page about the format of manpages (man man-pages 7) we learn that .TH can indeed take 5 arguments, namely:

.TH title section date source manual

By setting the headers we are in fact setting the name of the manual shown. This name is shown at the top centre of the manpage. For the curious, the following diagram shows where the other arguments end up.

title(section)       manual      title(section)

                      ...

source               date        title(section)

To complete the description of our script:

  • To make man read from standard input we use the “local file” -l flag (see man man).
  • To by default read README.md we use ${var:-default} to set a default value if $var is not set.
  • We use if [ -f "$file" ] to check if the file is a regular file before we try converting.

Tip: save this script as mdread in your $PATH and read markdown files with mdread in your terminal.

This is how the output looks:

       iso, a val and a ref can be subtyped to a box or tag, but a val cannot become a ref

      nor can a ref become a val, finally a box can become a tag]

      Apart  from  using generic functions, you can also use subtyping to just throw away
      your capabilities:

             val myRefCar = consume myIsoCar

Receiver reference capabilities
      Reference capabilities are checked when you are trying to access the value  or  the
      fields  of  a variable.  If you have an iso variable you can read any of its iso or
      val fields.  All other types of fields are read as a tag.

      At first, that seems odd, you might be wondering "If I have an iso why can't I read
      its  ref  field?"  The  reason is that an iso must maintain the property that it is
      isolated and that there is thus no other alias that can read or write to that memo‐
      ry.  This includes its fields.  If you were able to make an alias to one on the ref
      fields of an iso variable, you could still read from and write to the internals  of
      the  iso  trough  the alias of this ref field even if you passed the iso to another
      actor.  The same holds for trn and box fields.  val Fields are  fine  because  they
      are immutable, and they are always safe to read.

      The following table summarizes the restrictions.  The row indicates your capability
      on an object, the column specifies the capability the  object  itself  has  on  the
      filed you are trying to access.  Because you can't read fields form a tag, that row
      only contains "n/a".

      ▷            iso field   trn field   ref field   val field   box field   tag field
      ───────────────────────────────────────────────────────────────────────────────────
      iso origin   iso         tag         tag         val         tag         tag
      trn origin   iso         trn         box         val         box         tag
      ref origin   iso         trn         ref         val         box         tag
      val origin   val         val         val         val         val         tag
      box origin   tag         box         box         val         box         tag
      tag origin   n/a         n/a         n/a         n/a         n/a         n/a

      When you are calling a method on an object, the  restrictions  from  the  call-site
      still need to hold.  You can't call the method setRefField(...) on an iso variable.
      For this reason functions are annotated with a receiver reference capability.   You
      can  only  call  a  method that is compatible with your capabilities on the object.
      The default receiver reference capability of a method is box.

Refcap recap
      Reference capabilities guard the amount of references there are to a certain  piece
      of memory.

      A  variable is a pointer to an object.  Or to be more precise a variable references
      a capability.  When creating a variable, you need to assign a reference  capability
Manual page (stdin) line 293 (press h for help or q to quit)