Custom LaTeX Commands in Jupyter Notebooks

Jupyter
LaTeX
Author

Stefan Behrens

Published

August 5, 2025

As a mathematician I’ve been using LaTeX for a very long time. Over the years I’ve gotten used to a number of custom macros. Now that I’m using Jupyter Notebooks more and more, I’ve been looking for a convenient way to use my commands in this setting as well. Most importantly, I’ve internalized the commands below to an extent that I will type them even if a try not to.

% Numbers
\providecommand{\N}{\mathbb{N}} % natural numbers
\providecommand{\Z}{\mathbb{Z}} % integers
\providecommand{\Q}{\mathbb{Q}} % rational numbers
\providecommand{\R}{\mathbb{R}} % real numbers
\providecommand{\C}{\mathbb{C}} % complex numbers

% Math font styles
\providecommand{\mbb}[1]{\mathbb{#1}}
\providecommand{\mc}[1]{\mathcal{#1}}
\providecommand{\mf}[1]{\mathfrak{#1}}

% Arrows
\providecommand{\xra}[1]{\xrightarrow{#1}}

% Useful things
\providecommand{\inv}{^{-1}} % inverses
\providecommand{\del}{\partial}

By the way, if you’re wondering why I’m using \providecommand instead of \newcommand or \renewcommand, I’ve found the former to be less error prone since it doesn’t try to overwrite or override already existing commands. And it gets the job done just as well for me.

Things that work from the get-go

Before I continue, I should say that Visual Studio Code is my editor of choice. This matters, because it uses KaTeX as a rendering engine for LaTeX code in Jupyter Notebooks. KaTeX is not a full LaTeX distribution and only supports a small selection of commands. The full list is available here. A few of “my” commands work from the get-go:

  • \R gives \(\R\)
  • \Z gives \(\Z\)
  • \N gives \(\N\)
  • \set{...} serves as \{...\} and gives \(\set{...}\)
  • \Set{...} serves as \left\{...\right\} and curly brackets with auto-adapted size

However, \Q and \C do not give \(\mathbb Q\) and \(\mathbb C\)! While I don’t use \Q that much, not having \C is a problem.

Adding custom LaTeX commands in a Jupyter Notebook

Fortunately, it is possible to define custom LaTeX macros in a Jupter notebook. You just have to wrap the usual \newcommand{}[]{} or providecommand{}[]{}in dollar signs as in the following example:

$\newcommand{\C}{\mathbb C}$
Now I can write $\C$ instead of $\mathbb C$!
$\providecommand{\mc}[1]{\mathcal{#1}}$
Now I can write $\mc H$ instead of $\mathcal{H}$.

\(\providecommand{\C}{\mathbb C}\) \(\providecommand{\mc}[1]{\mathcal{#1}}\) Indeed \C and \mc H now give \(\C\) and \(\mc H\). Once declared, the macros are available in the entire notebook; they are not limited to the cell in which they are defined.

Indeed, this is a new cell and \C still gives \(\C\) although this was defined in a different cell. I could now even use this command before it was defined, that is, in cells above the one in which it is defined. However, this would produce an error the next time I open the notebook.

\(\providecommand{\Q}{\mathbb{Q}}\) There’s another minor catch. When using \newcommand as in $\newcommand{\Q}{\mathbb{Q}}$, say, make sure to put it in the top of the cell before any text. If you put it somewhere else (e.g. between paragraphs), then everything will be fine the first time you execute the cell, but starting from the second execution you’ll get this error:

ParseError: KaTeX parse error: \newcommand{\Q} attempting to redefine \Q; use \renewcommand

As I’ve already mentioned, I generally prefer to use \providecommand{} as it’s less error prone. This also holds in this case. $\providecommand{\Q}{\mathbb{Q}}$ will simply define \Q the first time around and do nothing any time after that, no matter where it was placed in the code.

To summarize, the best practice is as in LaTeX: * Put all your macros in the beginning of the document before the main text. * Try to use \providecommand instead of \newcommand or \renewcommand whenever you can.

From now on, the first markdown cell in my Jupyter Notebooks will start something like this:

# Title (or no title...)
$$
% Numbers
\providecommand{\N}{\mathbb{N}} % natural numbers
\providecommand{\Z}{\mathbb{Z}} % integers
\providecommand{\Q}{\mathbb{Q}} % rational numbers
\providecommand{\R}{\mathbb{R}} % real numbers
\providecommand{\C}{\mathbb{C}} % complex numbers

% Math font styles
\providecommand{\mbb}[1]{\mathbb{#1}}
\providecommand{\mc}[1]{\mathcal{#1}}
\providecommand{\mf}[1]{\mathfrak{#1}}

% Arrows
\providecommand{\xra}[1]{\xrightarrow{#1}}

% Useful things
\providecommand{\inv}{^{-1}} % inverses
\providecommand{\del}{\partial}
$$

Text goes here...

Loading custom LaTeX macros from a file into a Jupyter Notebook?

As I’ve said, over the years I’ve accumulated a set selection of custom macros and I’ve put them into a custom package. It would be great if I could use it in my Jupyter Notebooks as well. Unfortunately, it’s not as simple as writing $\include[my_package]$. Neither can I simply put my commands in a file my_commands.tex and write $\input{my_commands.tex}$.

I’ll look into this another time and if I find a solution, I’ll update the article.