Workflow: LaTeX

  1. Work environement
    1. Advanced: GitHub Actions
    2. Advanced/optional: Docker
      1. Docker with VSCode remotes
  2. Project structure
  3. Subfiles
  4. Packages and newcommands

Work environement

I use Visual Studio Code with the extension LaTeX Workshop. Most modern TeX processors have similar capabilities (syntax detection, bracket matching, synctex between source and pdf,…), but I prefer VSCode because I can use one program for everything.

As the TeX distribution I use TeXlive. If you’re on Ubuntu, like me, make sure to not install texlive using apt, as that version will probably be very outdated. See for example this guide for how to install the right version.

Advanced: GitHub Actions

Hosting the git repository allows to run some post-processing of the files, or “continuous integration” in the jargon, using GitHub Actions. When certain events are triggered in the repo (for example, pushing or publishing a tag), GitHub Actions executes the instructions stored in the .yaml files inside the folder .github/workflows.

I have a GitHub action that compiles a TeX file to pdf and also prepares a .zip file ready to upload to arXiv. To install the action, you only have to copy it in the folder and change the filename in line 5 to the name of your main .tex (it has to be located in the base directory of the repo). To execute it, you have to create and push a tag with

git tag -a versionnumber
git push --tags

After a couple of minutes, the .pdf and .zip files will be available at the “Releases” section of the GitHub repo page.

Advanced/optional: Docker

An alternative to install texlive in your computer is to use a pre-compiled version in the form of a Docker image. You can obtain the image with the command

docker pull texlive/texlive

This will take some time. You only have to run this command every time you want a new version of texlive. A new image is released every week, but it is reasonable to update just every couple of months.

Now we want to create a docker volume to store permanently the files, and populate it with the contents of your current folder containing the .tex files:

docker volume create myvol
docker run --rm -v "$(pwd)":/data -v myvol/app ubuntu cp -r /data /app

Now, the .tex files can be compiled with

docker run --rm -v myvol:/app -w /app/data texlive/texlive latexmk -f -pdf myfile.tex

When the processing finishes, you can check that the files are generated by mounting the volume

docker run --rm --name temp_ubuntu -it -v myvol -w /app/data ubuntu

and doing a ls inside the container. You will see the .pdf, and also all the auxiliary .aux, .out, .bib, etc. This is very useful if you want to keep them to speed up the compiling (for example, try to compile again, latexmk knows that everything is up-to-date), but don’t want them polluting your folders.

To retrieve the .pdf, without stopping the container, open a new terminal and execute the command

docker cp temp_ubuntu:/app/data/myfile.pdf .

Docker with VSCode remotes

Working with containers (or rather, inside containers) is much easier with VSCode and the Docker extension. Once that you have pulled texlive and created a volume, launch an interactive texlive container with

docker run -i --rm --name latex -v myvol:/app -w /app/data texlive/texlive

Now click the button in the bottom-left corner of VSCode (the >< symbol), and select “Attach to running container…” A new VSCode window will open, this time with the contents of the container. You can work inside the container as in a normal folder, editing files, viewing PDFs, using extensions… In particular, you can clone the git repository and sync all the files.

If you don’t want to remember all these commands, you can store them as VSCode tasks. Copy this file to .vscode/tasks.json in your directory (don’t forget to add it to .gitignore), and launch the tasks with Ctr+Shift+P > “Tasks: Run Tasks”.

Project structure

The LaTeX project files should live in their own directory, with no code or anything else. The directory should correspond to its own git repo.

The base directory should only contain LaTeX source files (.tex, .bib, .sty or .cls), and the configuration files for git and GitHub. Figures & cia should be organized in folder(s). The products of LaTeX’s compilation, including .pdf files, shouldn’t be tracked by git. This is achieved by a .gitignore file in the base directory:

*.pdf
!figures/*.pdf
*.aux
*.log
*.out
*.bbl

The first line excludes all .pdf files in the repo, but the second line makes an exception for the .pdf files in the figures folder (should add a similar exception for each folder). The rest of the lines exclude some of the usual files produced by the compilation. There are many more, depending on your packages and editor, so make sure to add all of them.

The plots generated by matplotlib or other plotting packages should be saved, if possible, as .pgf files, which is a TeX graphic format that can be used by including \usepackage{pgf} at the preamble of the main file, and then

\resizebox{0.45\textwidth}{!}{\input{figures/myplot.pgf}}

where you want to insert the plot. For certain plots, for example scatter plots with many points, a .pgf takes too much to compile. In those cases, if possible, use a .pdf. Non-vectorial formats like .png or jpg should be the last option.

Subfiles

For large projects, it’s better to keep each chapter or section in a separate file. The package subfiles allows for the compilation of both the whole document and each individual chapter file, inheriting the preamble of the parent file.

In the parent file, add \usepackage{subfiles} in the preamble, and \subfile{mychapter.tex} wherever you want to insert the chapter. In the chapter files, start with \documentclass[myparent.tex]{subfiles}, and write \begin{document} and \end{document} around your TeX code as usual. Chapter files don’t need a preamble before \begin{document}, they use the same as its parent. Now you can compile the parent file to get the complete document, or each chapter individually.

If you want some part of the text to be different depending on the file being compiled as the whole document or as a standalone chapter, use the command

\ifSubfilesClassLoaded{
    This text is only visible when compiled as an individual chapter.
}{
    This text is only visible when compiled as the whole document.
}

This is useful, for example, if you want to include the bibliography at the end of individual chapters.

Packages and newcommands

I personally prefer having all the \usepackage’s at the preamble of the main file. Another option is to collect them in a mypackages.sty file, and then load them with a single \usepackage{mypackages} at the preamble. In any case, each package has to be followed by a %-comment with a brief description, in order to make sure that the package is needed.

\newcommand’s are very useful to define common complex combinations. They should never be used to re-define primitive LaTeX commands (for example, don’t define \be and \ee to redefine \begin{equation} and \end{equation}, it reduces legibility and you can achieve a similar performance using autocompletion in you editor).

Commands should be defined in a mycommands.sty file (or even better, in several .sty files), and loaded with \usepackage{mycommands}. Also, if possible, document them with %-comments.