Having used LaTeX quite regularly in an academic context for the last couple of years, using groff as a (way) leaner alternative to LaTeX for writing my resume and cover letters while looking for a job has been quite refreshing1 and I definitely did not miss the unwieldiness of the LaTeX toolchain.
For authoring a groff document, I have the original groff source file and the
compiled .pdf
file (I use pdf-tools for that) opened side-by-side in
Emacs. But while compiling, auto-revert-mode
would try to re-render the pdf
too early, which would first fail and show an empty buffer for a few seconds
instead. This does not make for a great edit-compile-run loop. A solution exists
when using AUCTeX but remember we're trying to get away from TeX for a second.
I could replicate this for groff in an only slightly hacky way, which is quite the feat compared to the rest of my Emacs personal tricks and fixes. Quickly, it goes like this:
M-x compile
triggers (for example)make groff.pdf
.make
outputs"OUTPUT_FILE=groff.pdf"
to the compilation buffer.- a
compilation-finish-function
picks up the file name and reverts the corresponding buffer.
As far as I know, the only way to trigger some automatic actions at the end of
Emacs' compilation process is to populate compilation-finish-functions
. But
the only arguments passed to these functions are the compilation buffer and a
string such as "finished\n"
when the compilation succeeded. This does not say
anything about the output document so the crux of the trick is to pass that
information through the compilation buffer itself.
Here are some detailed steps for you to replicate:
- Have your
make
rule output the compiled file name like so
%.pdf : %.ms macros.ms @echo "OUTPUT_FILE=$@" # that's the important line groff -U -d paper=A4 -K utf8 -ms -T pdf $< > $@
- Add a function that picks up the output file name from the compilation buffer
and reverts its corresponding buffer (this is actually inspired from the
TeX-revert-document-buffer
function)
(defun my/after-compile (compile-buf desc) (let ((result (with-current-buffer "*compilation*" (save-excursion (goto-char (point-min)) (re-search-forward "OUTPUT_FILE=\\(.*\\)" nil t) (match-string-no-properties 1))))) (when result (let* ((filename (expand-file-name result)) (buf (find-buffer-visiting filename))) (when buf (with-current-buffer buf (revert-buffer nil t t))))))) (add-hook 'compilation-finish-functions 'my/after-compile)
- Set the
compile-command
variable. For example locally at the end of your groff source file
\# Local Variables: \# compile-command: "make groff.pdf" \# End:
- Trigger compilation using
M-x compile
orM-x recompile
.
There you have it, the (more) optimal groff workflow within Emacs. You're welcome.
Footnotes:
Even if roff's roots predate TeX!