← projects

Snipsmith

code · math

As a mathematician, I often take notes in Obsidian and write up documents in VSCode/Cursor, which means writing LaTeX in two editors that have nothing to do with each other. There exist great snippet managers for both: Obsidian Latex Suite and HyperSnips; the catch is that Latex Suite ships with a snippet library and HyperSnips ships with none, so for HyperSnips you go find someone else’s. I found myself having to develop separate muscle memories for each program, which wasn’t ideal.

To solve this problem, I built snipsmith. Snipsmith is a custom snippet manager for Obsidian and VSCode/Cursor that allows you to manage your snippets in one place. Setup is very simple: all snippets live in a single YAML file, and make snippets compiles the library into the formats Obsidian and VSCode/Cursor each expect, writing both at once. Define a trigger once and it works in both.

The 1D time-dependent Schrödinger equation being typed into Obsidian and VSCode, with the keystrokes for each shown between the two editor panes. The two keystroke sequences are nearly identical.
The same equation in both editors, from the same snippets.yaml. Both panes use the same recorded keystroke sequence to stay in sync.

Snipsmith ships with a comprehensive snippet library, heavily inspired by Latex Suite’s (which in turn draws on Gilles Castel’s), with many of my own snippets added. It currently contains 270 definitions, which compile down to 224 HyperSnips entries; the rest are Obsidian-only. (All of the snippets shipped with my dotfiles are managed through snipsmith.)

how it works

A snippet is a trigger, a replacement, and some options:

- trigger: pat
  replacement: \frac{ \partial }{ \partial t } $1
  description: Partial derivative wrt t
  options:
      math: true

Options shared by the whole library (I have auto: true on for almost all snippets) live in a defaults block at the top of the file.

make snippets compiles every snippet into the format each editor expects: Latex Suite reads a JavaScript array of objects with an options string, and HyperSnips reads its own format with a context guard and single-letter flags.

regex

The two formats disagree on regex. Latex Suite writes capture groups as [[0]], while HyperSnips uses inline JavaScript blocks (`rv = m[1]`) with groups numbered from one. The build script translates between them, so I only write the Obsidian form:

- trigger: ([a-zA-Z])und
  replacement: '\underline{[[0]]}'
  regex: true
  options:
      math: true

and HyperSnips gets \underline{`rv = m[1]`} automatically.

shared variables

I keep one list of 37 Greek letters and another of 77 symbol names, and reference them from inside triggers:

- trigger: '([^\\])({{GREEK}}|{{SYMBOL}})'
  replacement: '[[0]]\[[1]]'

This one rule means I don’t need to type a backslash for any named symbol. The compiled output differs by editor here too: Latex Suite has a variables feature of its own, so snipsmith writes a standalone variables file and keeps the reference as ${GREEK}, while HyperSnips gets the full list of symbols expanded inline.

validation

make check validates the whole file, and make snippets refuses to write anything if validation fails. It catches mistakes like unknown keys, invalid regex, and references to nonexistent capture groups, as well as problems specific to the output formats (e.g. backticks in regex triggers in HyperSnips, which would corrupt the file).

Generated files are committed to build/, so git diff build/ shows exactly what an edit to the YAML did to the output. CI runs validation on every push and fails if the build and committed files don’t match.

I hope you find the system useful! I truly believe that snipsmith provides a near-optimal experience for writing LaTeX fast, and if you too use both Obsidian and VSCode/Cursor, I think you’ll find it a big improvement. To try it, fork the repo, edit snippets.yaml, and run make snippets.