To edit LaTeX documents, I use three programs for compiling, editing and viewing, glued together by awesome and run via a Makefile. These three usual suspects are:
rubber
to compile LaTeX documents enough times so that all references are definedvim
/ Neovim to edit the TeX filezathura
to view the output PDF (with vim-friendly bindings)
We will now see how to write some Makefiles to automatically recompile LaTeX documents upon changes to the source TeX or figure files (PDF, SVG, etc.).
Minimal Makefile¶
Here is a minimal Makefile to recompile the document upon saving the TeX file.
It relies on inotifywait
to recompile the document upon changes to the
TeX source. On Debian/Ubuntu, you will find this tool in the
inotify-tools
package (sudo apt-get install inotify-tools
).
# LaTeX Makefile v0.33 -- LaTeX only PAPER=paper.tex # set the path to your TeX file here SHELL=/bin/zsh # for the while loop below all: ## Compile paper rubber --pdf $(PAPER) clean: ## Clean output files rubber --clean $(PAPER) watch: ## Recompile on updates to the source file @while [ 1 ]; do; inotifywait $(PAPER); sleep 0.01; make all; done # for Bash users, replace the while loop with the following # @while true; do; inotifywait $(PAPER); sleep 0.01; make all; done
After setting PAPER
to your TeX file’s name, run make watch
and
the document will be automatically recompiled any time you save it in your text
editor. Your PDF viewer should also reload the file automatically upon updates
(Zathura does it).
Addendum¶
An astute reader pointed out on Reddit
that the latexmk
tool does exactly the job of make watch
when
using the -pvc
(PreView Continuously) option:
latexmk -pdf -pvc paper.tex
However, in my experience LaTeX errors sometimes put this tool in an
inconsistent state, requiring a Ctrl-C and restart to update the PDF correctly.
At any rate, we will see below how we can extend our make watch
rule to
recompile SVG figures as well upon updates, which latexmk
doesn’t do.
Adding figures¶
Maybe you have SVG figures in your document, which you manually export to PDF
and include in your document via \includegraphics
. This process can be
automated in the Makefile by calling Inkscape from
the command-line. Here is an extended Makefile that will automatically
recompile PDF figures from their SVG sources upon saving:
# LaTeX Makefile v0.66 -- LaTeX + PDF figures ALL=$(wildcard *.sty *.tex figures/*.svg) PAPER=paper.tex SHELL=/bin/zsh FIGURES_SVG=$(wildcard figures/*.svg) FIGURES_PDF=$(FIGURES_SVG:.svg=.pdf) all: $(FIGURES_PDF) ## Build full thesis (LaTeX + figures) rubber --pdf $(PAPER) clean: ## Clean LaTeX and output figure files rubber --clean $(PAPER) rm -f $(FIGURES_PDF) figures/%.pdf: figures/%.svg ## Figures for the manuscript inkscape -C -z --file=$< --export-pdf=$@ watch: ## Recompile on any update of LaTeX or SVG sources @while [ 1 ]; do; inotifywait $(ALL); sleep 0.01; make all; done
Makefile of my PhD thesis¶
Rubber automates the compilation of LaTeX documents, and using
inotifywait
and inkscape
automates the process further. As an
example, below is the full Makefile I used to compile my PhD thesis, as well as
associated resources such as the (HTML 5) slides of my defense. The directory
structure was:
$ tree -L 2 ~/Documents/Thesis /home/scaron/Documents/Thesis ├── cleanthesis.sty ├── content ├── defense │ ├── images │ ├── index.html │ └── static ├── figures │ ├── pdf │ ├── static │ └── svg ├── Makefile ├── refs.bib └── thesis.tex
And the corresponding Makefile:
# LaTeX Makefile v1.0 -- LaTeX + PDF figures + PNG figures ALL=$(wildcard *.tex content/*.tex defense/index.html figures/svg/*.svg) MAIN=thesis.tex LATEX=rubber --pdf SHELL=/bin/zsh FIGURES_SVG=$(wildcard figures/svg/*.svg) FIGURES_PDF=$(subst svg/,pdf/,$(FIGURES_SVG:.svg=.pdf)) FIGURES_PNG=$(subst figures/svg/,defense/images/,$(FIGURES_SVG:.svg=.png)) all: $(FIGURES_PDF) $(FIGURES_PNG) ## Build full thesis (LaTeX + figures) $(LATEX) $(MAIN) # main run bibtex $(MAIN:.tex=) # bibliography makeglossaries $(MAIN:.tex=) # list of abbreviations, nomenclature $(LATEX) $(MAIN) # incremental run clean: ## Clean LaTeX and output figure files rubber --clean $(MAIN) rm -f $(FIGURES_PDF) $(FIGURES_PNG) figures/pdf/%.pdf: figures/svg/%.svg ## Figures for the manuscript inkscape -C -z --file=$< --export-pdf=$@ defense/images/%.png: figures/svg/%.svg ## Figures for my defense slides inkscape -C -z --file=$< --export-png=$@ watch: ## Recompile on any update of LaTeX or SVG sources @while [ 1 ]; do; \ inotifywait $(ALL); \ sleep 0.01; \ make all; \ echo "\n----------\n"; \ done help: # http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html @grep -P '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' .DEFAULT_GOAL := help .PHONY: help
It includes two minor changes compared to the previous Makefile: the compilation of both PDF and PNG figures (rewrite rules get a bit more complex) and the nice help snippet from the marmelab blog.
Integrating Inkscape and LaTeX¶
There is room for improvement in the integration between Inkscape and LaTeX. So
far, I have been using the textext extension to embed LaTeX
equations into SVG files. However, with this approach one needs to coordinate
by hand the font size between the SVG and LaTeX documents. For instance, when
you scale the figure in \includegraphics
, its text gets scaled as well.
Looking at the LaTeX page of the Inkscape wiki and the related
svg-inkscape LaTeX
package, it seems one can alternatively process SVG figures directly from
LaTeX. This has the benefit not only of using the same text scaling between
figure and document, but also enables you to use other contextual macros such
as \ref
and \cite
. One should definitely try it out 😉
Discussion ¶
Feel free to post a comment by e-mail using the form below. Your e-mail address will not be disclosed.