Troff realtime preview for acme.

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

   #!/usr/local/plan9/bin/rc

   . $PLAN9/lib/acme.rc
   nl='
   '

   tmp=/tmp/autoroff.$pid

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

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

   if(! winread tag | 9 grep -s Put)
       echo -n ' Put' | winwrite tag
   reroff
   wineventloop &
   psv --watch $tmp.ps
   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:

   while(`{read}){
          troff ... |lp -dstdout > x.ps
          page x.ps
   }

To post a comment you need to login first.