Simple groff compiler for vim

When writing documents in vim, it’s nice to have a quick way of compiling them into the desired formats. In my case, I compile my groff files into pdfs while at the same time having a preview in zathura. Zathura automatically detects changes in pdfs and reloads accordingly, which is nice.

The compiler code

Below, I will describe the code in short.

_FILE=$(readlink -f "$1") 
_DIR=$(dirname "$_FILE") 
_ARGS="$(grep -oP -- "$_PRFX.*$" "$_FILE" |  sed -s "s|$_PRFX||")" 
cd "$_DIR" || return 
case "$_FILE" in 
*\.ms)  preconv "$_FILE"                                            \ 
    | refer                                                         \ 
    | tbl -Tpdf                                                     \ 
    | eqn -Tpdf                                                     \ 
    | pic -Tpdf                                                     \ 
    | groff -k -ms $_ARGS -dpaper=a4 -P-pa4 -P-e -Tpdf              \ 
    | gs                                                            \ 
        -q                                                          \ 
        -dNOPAUSE                                                   \ 
        -dBATCH                                                     \ 
        -dPDFSETTINGS=/prepress                                     \ 
        -sDEVICE=pdfwrite                                           \ 
        -dPrinted=false                                             \ 
        -sOutputFile="$_BASE.pdf" - 

The script above is called compile and is intended to be used for multiple file types. In this version, I have only implemented support for .ms files. First, the filename is read from the first argument to the script. From the filename, I determine the directory path and the "base name" without the filename’s extension. In the file I search for the pattern ---COMPILE: as it may contain additional arguments for the compiler (used above as $_ARGS).

The script then changes the directory to the file’s directory and executes a chain of programs. First, preconv is executed to handle unicode characters. Then, refer handles references, eqn handles mathematical expressions, pic handles pictures, groff compiles everything into an a4 pdf using the ms macro set, and finally, Ghostscript runs post processing and embeds used fonts into the pdf (while preserving hyperlinks).

Everything is then being outputted to the same "base name", but as a pdf file.

Usage in vim

In vim, I have the following key binding set to compile the document upon request.

map <leader>c :w! silent !compile <c-r>%<CR><Esc>:redraw!<CR> 

There isn’t much to say about this. The document is being saved, compiled, and then vim is being redrawn (to avoid glitches).


My usual workflow for writing documents in vim, using the above compiler, consists of me first starting a terminal (with tmux). I then open a new tab, start vim, and setup everything for a base document in groff. After that, I run the compiler to create an empty pdf. In the first tab, I execute zathura to view the pdf. As I use dwm (a tiling window manager), I have vim on one side of the screen and zathura on the other. Simple and functional!