I’ve really been enjoying writing my dissertation using Quarto, a nice new typesetting/computing wrapper around pandoc developed by the good folks at Posit. I thought I’d write up the tips and tricks I had to develop to get my document looking how I wanted it, in case anyone else ran into the same problems as me. I’m sure there are smarter ways to solve all the problems I list here, but this is what worked! I’ll update this post as I keep writing.
Who is this guide for?
I’m aiming this guide at someone who is interested in getting their document looking just so. If you want to just get words down on a page, use the default Quarto settings, or just use Word. There’s no shame in caring about substance over style.
Okay they’re gone. That’s insane to me. If it’s got my name on it, I want it to look right.
Oh, also, this is about writing a dissertation — a book. If you’re working on a
paper, basically everything here applies except all the stuff I put in _quarto.yml
you’ll put in the YAML header of your document. And when you run quarto render
you’ll have to tell it to render the document instead of just running it without
specification.
Finally, I assume you have passing familiarity with markdown and you’ve glanced at how Quarto works.
Setup
Before you start
- Download Quarto
- Pick your editor. I use Visual Studio Code because I’ve got it set up just how I like it for writing, but the tips I’ve got here should mostly carry over. I’ll try to make it clear when something only applies to VS Code. Whatever you end up picking, be sure to install the Quarto plugin.
- Download and use Zotero and the Zotero plugin,
Better BibTeX. Zotero
really is the best citation management software, and Better BibTeX makes it easier
to work with Quarto by automatically generating your citation keys and
.bib
files, and keeping those up to date whenever you add new references.
Project Organization
I’ve got my project organized like this:
dissertation/
├── _quarto.yml
├── index.qmd
├── cell.csl
├── dissertation-reference.docx
├── henac.bib
├── parts/
│ ├── appendecies/
│ │ ├── code.qmd
│ │ ├── mat-meth.qmd
│ │ ├── processing-flow.qmd
│ │ ├── validation.qmd
│ │ └── figures/
│ │ └── {figure files}
│ ├── introduction/
│ │ ├── intro_enac-in-the-body.qmd
│ │ └── figures/
│ │ └── {figure files}
│ ├── introduction.qmd
│ ├── results/
│ │ ├── results_activating-conditions.qmd
│ │ ├── results_transmembrane-domain.qmd
│ │ └── figures/
│ │ └── {figure files}
│ └── results.qmd
├── todo.md
└── update-todo.sh
My basic thinking is to put non-writing stuff in or near the root directory, and put
all the actual writing into parts/
, except index.qmd
, which has
to be in the root directory. As you can see, you end up generating a ton of files.
Even though you could have everything in one big writing/
directory, or even just
dump it all in the root dir, you’d end up taking ages to find everything. I also like
to know which figure goes with which .qmd
.
Essentially, I want to have separation
of concerns. If something is wrong with code or styling, I look in the root dir.
If something is wrong with what I’ve written (and there’s always something), I
can quickly find the .qmd
file by following the logic of the book itself. If you’re
young
you’re probably more used to searching instead of navigating a file tree,
so this probably doesn’t matter as much and you can just dump stuff wherever you want.
I honestly wish I were you.
Writing
Citations
To get your citations working nicely with Quarto, I recommend you set up an auto-export
in Better BibTeX. To do that, hit File > Export Library...
in Zotero to open the
export dialogue. Select Better BibLaTeX
as the format and be sure that Keep updated
is checked. Then hit export and give it a name and save it into your Quarto directory.
Zotero will now automatically re-export your .bib
file whenever you modify, add,
or remove a reference. I have found that by the time I alt-tab back to VS Code and have
typed in the first few characters of a reference key it’s already done. The thing is
magic.
cell.csl
is a Citation Style Language file. This
sets up your citations to look (in this case) like they would in Cell. There are
literally thousands of these to choose from. Quarto also has a default style, but
I find author/year citations to be unwieldy.
You point to your citations and style with these YAML keys:
bibliography: henac.bib
csl: cell.csl
I also like my PDF format to have clickable citation links, but I don’t want those links to look blue (PDFs are printed, and blue on a printed document looks so unprofessional). Here’s the YAML:
format:
pdf:
link-citations: true
colorlinks: false
Figures
I have all my figures in subdirectories of the parts rather than in the root directory
mostly for organizational purposes, as I said. If you prefer to have everything lumped
together this is less important. If, however, you like having your writing separated
out but will frequently be re-using figures across chapters/parts, you might consider
a root level figures/
directory and telling Quarto to execute from the root, rather
than from the file location. To execute at the root rather than wherever the .qmd
file is, you’d want to add this to quarto.yml
.
project:
execute-dir: project
What this changes is what it means when you enter a path to a figure or data. By default (and how I have my project set up), if my project looks like this:
root/
└── intro/
├── intro.qmd
└── figures/
└── {figure files}
and I tell Quarto to include figures/enac.png
in the file root/intro/intro.qmd
,
it’ll look for the file at
root/intro/figures/enac.png
. However, with the execute-dir
set to project
,
it would instead look for root/figures/enac.png
. That way you can use the same
path in multiple different files and all refer to the same figure.
Once you’ve decided on a structure, writing is pretty frictionless. Unlike writing in LaTeX, I spend almost no time fighting with Quarto. I write my markdown, render it, and it looks how I like it. That is, of course, after I did the initial setup to style my document.
Asides
I have ADHD, which means I get easily distracted and love going on tangents. Since my dissertation is something that only a few people will ever read and has only to conform to the most basic requirements, I decided I wanted to capture that by writing asides in the margins, like so:
It’s very easy (perhaps too easy) to incude these asides in Quarto, so I’ve written quite a few. Both PDF and HTML outputs handle them well, but Word dumps them into the paragraph as a normal sentence. This really breaks up the flow of the writing, since asides are usually self-contained thoughts. I wrote a Lua filter to remove them automatically from the DOCX output:
return {
Span = function (elem)
if quarto.doc.is_format('docx') then
if elem.classes:includes('aside') then
return ""
else
return elem
end
end
end
}
I put this filter in my root dir as no_asides.lua
, then added this YAML to the
quarto project:
format:
docx:
filters:
- no_asides.lua
Styling
Handling fonts
First off, you should pick a nice font. However, many fonts (even ones you pay for!) don’t have all the glyphs we need as scientists. For instance, I’m using Charter. But Charter doesn’t have greek characters or mathematical symbols! This is fine for HTML and DOCX formats, as they’ll handle fallback all on their own. However, LaTeX does exactly what you tell it and nothing more. When it runs into a glyph your font doesn’t have, it will warn you (an warning like “Missing character:” in the log) and just put a blank space there.
To get around this problem, I installed Fira Sans which looks pretty good and has most of the glyphs you could want. Then, I set up the ucharclasses package, which lets you define behavior when entering and exiting a Unicode block. For instance, I know that when LaTeX encounters a Greek glyph, it should switch to Fira Sans, then switch back when it encounters a Latin glyph. Here’s the YAML:
format:
pdf:
include-in-header:
- text: |
\usepackage{fontspec}
\newfontfamily\symbolfont{Fira Sans}
\setmainfont{Charter}
\setsansfont{Montserrat}
\setmonofont{JetBrains Mono NL}
\usepackage{newunicodechar}
\DeclareTextFontCommand{\textfallback}{\symbolfont}
\newunicodechar{→}{\textfallback{→}}
\newunicodechar{₂}{\textfallback{₂}}
\newunicodechar{⁻}{\textfallback{⁻}}
\newunicodechar{ă}{\textfallback{ă}}
\newunicodechar{≠}{\textfallback{≠}}
\usepackage{ucharclasses}
\setTransitionsForGreek{\begingroup\symbolfont}{\endgroup}
The first block loads the fonts I’m using throughout the document.
The second block uses the newunicodechar
package to define behavior for specific
symbols that don’t neatly fall into a block for ucharclasses
to handle.
The final two lines set the behavior to and from Greek.
Conclusion
That’s most of what I’ve done so far! I’ll reproduce my full YAML config here so you can see how it all comes together.
project:
type: book
book:
title: ENaC isn't ASIC
subtitle: "A Study of Various Activating Mutations and Conditions of the Epithelial Sodium Channel"
author:
- name: "Richard Posert"
affiliation: Baconguis Lab, Vollum Institute, OHSU
date: "7/21/2023"
chapters:
- index.qmd
- part: parts/introduction.qmd
chapters:
- parts/introduction/intro_enac-in-the-body.qmd
- part: parts/results.qmd
chapters:
- parts/results/results_activating-conditions.qmd
- parts/results/results_transmembrane-domain.qmd
- parts/references.qmd
appendices:
- parts/appendices/mat-meth.qmd
- parts/appendices/processing-flow.qmd
- parts/appendices/validation.qmd
- parts/appendices/code.qmd
navbar:
logo: figures/other/domain-cartoon_ECD.png
search:
location: navbar
type: overlay
downloads:
- pdf
- docx
output-file: posert-dissertation
csl: cell.csl
toc: true
bibliography: henac.bib
format-links: true
format:
html:
filters:
- lightbox
lightbox:
match: auto
mainfont: Charter
theme:
light: flatly
dark: darkly
pdf:
documentclass: scrbook
pdf-engine: latexmk
pdf-engine-opt: --xelatex
latex-max-runs: 3
keep-tex: false
link-citations: true
colorlinks: false
geometry:
- left=2in
- right=2in
- marginparwidth=1.5in
- twoside=true
include-in-header:
- text: |
\usepackage{fontspec}
\usepackage{newunicodechar}
\newfontfamily\symbolfont{Fira Sans}
\setmainfont{Charter}
\setsansfont{Montserrat}
\setmonofont{JetBrains Mono NL}
\DeclareTextFontCommand{\textfallback}{\symbolfont}
\newunicodechar{→}{\textfallback{→}}
\newunicodechar{₂}{\textfallback{₂}}
\newunicodechar{⁻}{\textfallback{⁻}}
\newunicodechar{ă}{\textfallback{ă}}
\newunicodechar{≠}{\textfallback{≠}}
% naughty naughty but who cares, just don't use a non-breaking hyphen
\newunicodechar{‑}{\textfallback{-}}
\usepackage{ucharclasses}
\setTransitionsForGreek{\begingroup\symbolfont}{\endgroup}
\usepackage{lscape}
\newcommand{\blandscape}{\begin{landscape}}
\newcommand{\elandscape}{\end{landscape}}
docx:
reference-doc: dissertation-reference.docx
filters:
- no_asides.lua