11 KiB
note-taking with typst and neovim
2023-08-14
A while back, I saw Gilles Castel's series of blog posts about his note-taking setup with LaTeX and Vim. I was quite inspired by the idea, and I even tried it for a while, but gave up in the end. It was less effort to start writing in a plain text file than to write in LaTeX. So, these were my goals for a note-taking system:
- Taking notes should be convenient. I should be able to to open a new notes page and start writing in a short amount of time.
- The syntax for the notes should be easy to remember. If I need to look up syntax for common things, I'm wasting time.
- I should be able to put basic math, figures, etc. in my notes.
Eventually, I found a typesetting system called Typst. Typst is kind of a mix between LaTeX and other formats like Markdown. On one hand, it's designed for working with math and other technical subjects, like LaTeX. On the other hand, it has a relatively simple syntax reminiscent of Markdown. Compare these two snippets:
LaTeX:
Then, starting from 2:
\begin{enumerate}
\item If the current number is composite, we skip to the next number.
\item Mark all factors of the current number as composite.
\item Move to the next number.
\end{enumerate}
Typst:
Then, starting from 2:
+ If the current number is composite, we skip to the next number.
+ Mark all factors of the current number as composite.
+ Move to the next number.
Because of the above advantages, I decided to start writing things down in Typst. In this blog post, I'll be documenting my process and tools for Typst note-taking at the time of writing.
neovim setup
Currently, I'm using the typst.vim plugin to integrate Typst with Neovim.
It provides basic syntax highlighting, and recognizes .typ
files as Typst files.
The plugin also has a "watch" command that compiles your Typst file on change to a PDF.
However, I haven't figured out how to have it display compiler errors, so I have this in my Neovim config:
function TypstWatch()
vsp
vertical resize 20
exec 'terminal ' .. 'typst watch ' .. expand("%:")
exec "norm \<c-w>h"
endfunc
nnoremap <silent><leader>fc :call TypstWatch()<cr>
nnoremap <silent><leader>fr :silent exec "!zathura --fork " . expand("%:p:r") . ".pdf &"<cr>
This sets up a bind to open typst watch
in a terminal pane on the right,
with another bind to open the PDF in Zathura.
Every time I save the content in my text editor, it updates the PDF seamlessly.
It looks like this on screen:
templates
Users of LaTeX or Typst often use templates in order to configure things like document size, layout, fonts, style, and so on. Instead of redefining these settings every time, we can just import them from a file. I won't go into detail here; read the relvant Typst documentation for information. For reference, you can find my own templates at GitHub along with instructions for using them. The developers of Typst are working on better ways of packaging templates at the moment, so beware that they're not the best example of how to write templates.
Anyways, you always need to import the templates for every new document you make,
and you also need to pass in parameters like the title of the document.
Typing all this boilerplate manually would be tedious, if done for every document.
This is where UltiSnips comes in handy.
UltiSnip provides snippets, which are templates of text that you can rapidly paste in the editor.
For example, I've set it up so typing today
and pressing Tab prints out the current date:
Snippets also support slots where you can type your own text. Every time Tab is pressed again, it moves to the next slot instantly. Here, you can see my snippet for new documents in action:
With this setup for Neovim, I have achieved the goal of being able to start writing new notes rapidly. It only takes around twenty seconds to open a new file in the editor, then fill out the template information, after which I can start writing.
version control
When dealing with any textual content, a good practice is to put it under version control like Git. This is the norm for code, but it's also viable for LaTeX/Typst content. The main advantages of this are:
- You're sure you won't accidentally delete any data,
- You can roll back to older versions, and
- You can easily view what changed between versions.
For that reason, I set up a private GitHub repo for storing all my notes in a single folder. Besides that, I also set up the templates as a submodule. Like this, I can clone the notes repository and also get my templates set up at the same time.
math & code
In the notes I'm writing, I often have to deal with mathematical expressions and code. You can see here that Castel gets a lot of use out of UltiSnips for rapidly typing math in LaTeX. However, in Typst, I find that these snippets are mostly unnecessary, since it has cleaner, simpler syntax for math in general.
For example, this is the LaTeX syntax for a fraction:
\frac{3}{2}
Typst has a much more minimal syntax:
3/2
Typst also has a simpler math "environment" syntax.
Anything between dollar signs $"like this"$
is inline math.
To use display math, add any spacing $ "like this" $
.
With auto-pairs for Neovim,
it only takes a single keystroke to start a math expression,
and another to end one.
See it here in action:
Another bit of syntax sugar that's built-in to Typst is support for code blocks.
Inline code is introduced by single backticks,
while multi-line code is introduced by triple backticks.
This is exactly the same syntax as in Markdown, which is much more familiar than \begin{verbatim}
.
It also provides syntax highlighting out of the box, without needing to import lstlisting:
figures
Being able to draw diagrams in the notes is also a necessary feature. This part of my setup is mostly unaltered from Castel's own method of drawing figures. Read his own blog post regarding drawing figures for the best explanation of how it works. To briefly summarize his post, Castel uses Inkscape to draw figures, with a shortcut script that accelerates the process. He says that he can draw almost as fast as his lecturers draw on the blackboard, although I'm not nearly skilled enough to do the same. Here's an example from his blog post:
Again, read Castel's blog post about drawing figures. Here, I will only explain the modifications I made to his process, assuming you already know how it works.
So, first of all, Castel's shortcut manager (GitHub)
is quite useful, and does indeed speed up drawing considerably.
However, it's built to deal with LaTeX only,
which is not compatible with my notes.
Therefore, I patched his scripts so that they hook into Typst rather than latexmk.
The results of this are available on GitHub.
Besides that, I also have a snippet for figures in Typst.
It has slots for inputting the filename/ID of the figure, and also a caption for it.
Once the snippet is pasted, I can hover over the filename and press <leader>ff
,
which opens that figure in Inkscape, or creates it if it doesn't exist.
Then, I can draw things, and have it appear in my notes.
Here's a full demo of drawing a figure (click for a non-gif version):
For now, there's the limitation that there is no equivalent of PDF+LaTeX for Typst. This means that the font for the document is not synced to the font in the figures themselves.
linking/references
Often, when I'm writing notes for a certain topic, I might want to reference another.
Now, it is possible to use a relative path link to another PDF,
but that doesn't allow for referencing specific pages or sections.
Castel himself solved this problem with Instant Reference,
which creates links with the phd://
protocol, which is then handled specially by a script.
However, I decided to make my own rewrite of the script in Python, in contrast to the original written in JavaScript.
I prefer having my packages managed by the system's package manager, rather than by npm
.
Python is better in this regard, because Arch Linux packages essential Python packages under extra/python-.*
.
I have a bind set up to instantly copy a link to the currently viewed page in the PDF. For example, here I link to my algorithm notes in a document:
An extra feature I have compared to Castel's version is referencing specific sections. This is helpful when you modify notes afterwards and a page number points to different content. A key bind in my PDF reader triggers a rofi menu where you select one of the sections visible on the current page, after which you can paste the link to that section seamlessly in your notes.
conclusion
I've been using the above system for taking notes on competitive programming problems and computer science for a few months. I think that my goals of having a system for notes that was convenient, easy, and featureful has been accomplished. Indeed, I haven't had to open up a plain text document for taking notes in quite a while; everything is in Typst now.
If you want to see the real configuration files behind all of it, check out my dotfiles on GitHub.
The important files are src/.local/bin/typst-figure
, and src/.config/nvim/typst.vim
.
Maybe this post will sway you to check out Typst. But if it hasn't, look at the example on their GitHub page. Hopefully, one day Typst will get wider usage, because it's a great typesetting system.