Tips and tricks

Troff in Technicolor (2011/04/12)

Someone asked on 9fans today how one goes about getting coloured troff graph/charts/&c. Sape Mullender graciously provided how he does this.

From: Sape Mullender sape@pla... Subject: where to get color troff? Date: Tue, 12 Apr 2011 09:33:47 +0200

I use these macros for generating color:

.de CL
\\X'PS \\$1 \\$2 \\$3 setrgbcolor'\\c
.de BK
\\X'PS 0 0 0 setrgbcolor'\\c
.de EM
\\$3\\X'PS 1 0 0 setrgbcolor'\\$1\\X'PS 0 0 0 setrgbcolor'\\$2

They only work if you generate postscript (you can, of course, turn that into pdf as well).

.CL r g b

sets the color to the rgb values (0 0 0 being black, 1 1 1 being white,

0.5 0.5 0.5 being middle grey)

sets the color to black.

.EM "string1" "string2" "string3"

(emphasis), where strings 2 and 3 are optional prints string3 in the current color, followed by string1 in red and string2 in black (with no space between strings 3, 1 and 2 — they work as .B or .I in the .ms macro package.


9fans post

Using Inferno to serve files to Plan 9 in Qemu (2010/08/17)

Venkatesh Srinivas has posted a very brief guide that lets you serve files from Inferno to Plan 9 in Qemu.

I run Plan 9 in qemu, but I run neither fossil nor any other (major) disk file server in qemu. Instead, I have Inferno on my host serve files to Plan 9.

To accomplish this:

  1. I installed Plan 9, as normal, into a qemu disk image, with fossil as my fileserver
  2. I tarred up my root and copied it to my host
  3. I patched the 9 boot program to accept a file server on port 6666 rather than 564 (styx instead of 9fs)
  4. I untarred the root fs and had Inferno: ‘styxlisten -A tcp!*!6666 export /plan9’
  5. Start the both (qemu and inferno) together.
  6. Profit!

Original 9fans post.

avoiding auth ndb entry for your plan9 site (2010/08/02)

here is a trick that lets one mount a plan9 filesystem on another site without having to create a ndb entry to specify the domain name of the auth server.

when your auth domain is also your dns domain name. one can register p9auth subdomain and point it to your auth server:

lets say your dom is, then your auth server becomes

this works as authdial() in libauthsrv uses that default subdomain if here are no keys in your ndb for that particular auth domain.

Putting the 9 in S9FES (2009/07/19)

Scheme 9 from Empty Space (s9fes) is a work-in-progress implementation of Scheme, only experimentally ported to Plan 9. The compilation is simple enough, issuing ‘mk’ in the root source directory. However, properly making use of all of the libraries it comes with requires five minutes of configuration.

For the sake of organisation,

    term% mkdir $home/path/to/s9fes/sys # a rose by any other name...
    term% cp $home/path/to/s9fes/s9.^(scm image) $home/path/to/s9fes/sys
    term% mkdir $home/lib/s9fes

then making use of such, we do the following because s9fes uses environment variables, in the spirit of modern UNIX, to find its essential files (i.e., libraries and images):

    term% echo '#!/bin/rc


            for(i in lib contrib sys)
                bind -a $s9inst/$i $home/lib/s9fes


            $s9inst/s9' > $home/bin/rc/s9
    term% chmod +x $home/bin/rc/s9

and invoke the script s9 for actual use. Aside from the creation of lib/s9fes, which is a trade-off for organisation, this configuration is noninvasive and upgrade withstanding, for use until the Plan 9 port is finalised.

N.B.: In the above script, it might be necessary to define LIBDIR=$S9FES_LIBRARY_PATH – on modern UNIX systems, $S9FES_LIBRARY_PATH is a colon-separated list of paths containing scm and image files for s9fes, while $LIBDIR is the specific system-wide copy of s9fes/lib. On Plan 9, however, we don’t require the distinction due to the use of binds (and all library file names have to be distinct anyways, due to the way they are loaded from within s9fes).

Troff realtime preview for acme. (2009/07/17)

A while ago Russ Cox posted this script to keep a realtime preview of a troff document being edited with Acme:

One really nice thing about troff is that it is very fast. It hasn’t changed appreciably in decades, so it is riding out the hardware performance improvements quite nicely.

I was marvelling about how when I middle-click a troff | page command line in acme it just pops up instantly, and I decided to write a little shell script to do that for me.

This script watches the acme window it is executed in, and every time you type a newline or cut/paste with the mouse, it re-runs troff with the window contents, updating a postscript file being watched by gv –watch.

There is a slight lag before gv notices the file has changed, but it’s certainly good enough, and even better than repeatedly clicking Put and then executing the troff command.

If one were going to write a real command, you’d want to reroff in the background, waiting for pauses in the editing. But for a shell script, this isn’t bad.

One unfortunate effect is that because the window is attached to a program, Undo, Redo, and Put go away and have to be added on the other side of the tag | .

Enjoy. Russ


   . $PLAN9/lib/acme.rc


   fn reroff {
       9p read acme/$winid/body >$
       { 9 tbl $ | 9 troff -ms | tr2post >$tmp.ps_
           && mv $tmp.ps_ $ } >[2]/dev/null

   fn event {
       case KI
           if(~ $9 $nl)
       case KD MD MI
       case Mx MX Ml ML
           winwriteevent $*

   if(! winread tag | 9 grep -s Put)
       echo -n ' Put' | winwrite tag
   wineventloop &
   psv --watch $
   kill $apid
   killall 9p  # BUG
   rm $tmp.*

Update: Stuart M (aka stu9) notes in #plan9 that Presotto had posted back in 2001 to 9fans about how he usually kept a window running the following loop:

          troff ... |lp -dstdout >

Installing ‘Standard’ Inferno Fonts (2009/02/13)

Update: sqweek has been kind enough to ignore some dumb laws and conveniently host a copy of the fonts for easy download at Thanks!

The original Inferno fonts are not free (as in freedom) and can only be distributed together with the ‘official’ Inferno distribution.

Because of this restriction the source distribution and other derivative Inferno packages can’t include fonts, and if you have built Inferno from source many applications wont work.

Here is a script by caerwyn that used to be included with acme-sac which will download the fonts from VitaNuova’s site and install them:

    load std

    if {ftest -d /fonts/lucidasans}{
            echo 'error: /fonts directory already exists'

    mkdir /fonts
    mkdir /tmp/inferno
    cd /tmp/inferno

    webgrab -v -r -o - > inferno.tgz
    gunzip <inferno.tgz > inferno.tar
    gettar < inferno.tar
    gunzip <install/inferno/1178807193.gz >install/inferno/1178807193
    archfs -m mnt/wrap install/inferno/1178807193 /fonts
    cp -r mnt/wrap/fonts/* /fonts

    unmount mnt/wrap
    rm -rf /tmp/inferno

It is strongly recommended that anyone working on Inferno-based projects replaces the ‘standard’ fonts with a free set of fonts like acme-sac has eventually done by using the Vera font set.