Reading markdown like a man
#!/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 (seeman 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)