How to define a macro in a Jupyter cell?

Hi!

I want to define a macro in a Markdown text cell of a Jupyter notebook. But it seems that we cannot define it.

For example, I want to define a macro which formats vectors. The code in the cell is:

\newcommand{\vect}[1]{{\mathbf{\boldsymbol{{#1}}}}}

This is the vector $\vect{x}$.

The rendering is shows the “newcommand” statement, and I do not want that.

A possible way to define a macro in a Jupyter cell is to put a dollar in front of and after the macro.

$\newcommand{\vect}[1]{{\mathbf{\boldsymbol{{#1}}}}}$
This is the vector $\vect{x}$.

and the rendering is:

image

This is the trick used at Latex macros in Jupyter (iPython) notebook not rendered by github, but the topic is slightly different.

Is this a correct way to solve this?

Best regards,

Michaël

PS

Michael,

In a jupyter notebook markdown cell I can enter a new LaTex command like:

$\newcommand{\partials}[2]{\dfrac{\partial #1}{\partial #2}}$

and then use it as:

$$\partials{L’}{q_j}$$.

In the notebook, the newcommand line will be hidden and the use of the \partials command works as expected. It displays a nice partial derivative.

BUT when I download the notebook as PDF via LaTex I get an error:

! Undefined control sequence.
l.537 [\partials
{L’}{q_j}]
?
! Emergency stop.

I can work around the error by downloading to TeX, opening the file in an editor (say GNOME LaTeX), and manually moving the line:

\(\newcommand{\partials}[2]{\dfrac{\partial #1}{\partial #2}}\)

from the document body up into the preamble and deleting the unneeded \( and \). I can then save the tex file and compile to get a correct display in the PDF document. A workaround that complex isn’t much of a workaround.

I have tried putting the new command up in a RawNBConvert cell at the top of the notebook without the leading and trailing $ marks. That gets the new command into the tex file at the top of the document body, right after \maketitle. But to get it to work in the notebook I have to also define it in a markdown cell, and then LaTex throws an error at the second occurrence saying Command \partials already defined.

Searching finds many versions of this question being asked, yours among them, and sadly no working answers. Is there a trick I’m missing, or is this a true bug that has existed for years with no fix? Did you ever get something that works?

Since there have been no answers to either the original question or my collaborating comment, and I have been unable to find an answer in the docs or in other searching, I have entered the issue as a bug, LaTeX newcommand does not propagate to tex document correctly · Issue #1650 · jupyter/nbconvert · GitHub.

However, this does not seem to work for jupyter lab.
For the lab, you need this trick.

I quickly tried the JL trick and it works nicely in both the JL display and the LaTex export. I extended the trick sample a bit.

<div hidden>
\newcommand{\require}[1]{}

$\require{begingroup}\require{newcommand}$
$\gdef\vec#1{\boldsymbol{#1}}$

\vskip-\parskip
\vskip-\baselineskip

</div>

<div hidden>

$\gdef\part#1#2{\dfrac{\partial #1}{\partial #2}}$

\vskip-\parskip
\vskip-\baselineskip

</div>

Apparently you only issue the \newcommand and \require statements once, Otherwise you get a LaTeX compile error.

So we have tricks that work in Jupyter notebook and Jupyter lab. They are unfortunately not the same tricks, so you cannot edit the same ipynb in both tools and get the same results. This sounds like a work-around (which is good) but not a full solution.

Is there a good place to document this so other folks will not have to dig it out in bits and pieces?

1 Like

Hi, the following didn’t work for me, but this did (and avoided using gdef):

\[ 
\iffalse General-purpose macros for parents and stuff \fi
\renewcommand{\deg}{{^{\circ}}}
\providecommand{\rbr}{}\renewcommand{\rbr}[1]{{\left({{#1}}\right)}}
\providecommand{\abr}{}\renewcommand{\abr}[1]{{\left\langle{{#1}}\right\rangle}}
\providecommand{\cbr}{}\renewcommand{\cbr}[1]{{\left\{{{#1}}\right\}}}
\providecommand{\sbr}{}\renewcommand{\sbr}[1]{{\left[{{#1}}\right]}}
\providecommand{\pipe}{}\renewcommand{\pipe}[1]{{\left|{{#1}}\right|}}
\providecommand{\ppipe}{}\renewcommand{\ppipe}[1]{{\left\|{{#1}}\right\|}}
\providecommand{\floor}{}\renewcommand{\floor}[1]{{\left\lfloor{{#1}}\right\rfloor}}
\providecommand{\ceil}{}\renewcommand{\ceil}[1]{{\left\lceil{{#1}}\right\rceil}}

\iffalse Semantics macros \fi
\providecommand{\iet}{}\renewcommand{\iet}[3]{{\textrm{if } {{#1}} \textrm{ then } {{#2}} \textrm{ else } {{#3}}}}
\providecommand{\t}{}\renewcommand{\t}[1]{{\textrm{true}}}
\providecommand{\f}{}\renewcommand{\f}[1]{{\textrm{false}}}

\iffalse Compilers macros \fi
\providecommand{\fst}{}\renewcommand{\fst}[1]{{\textrm{FIRST}({{#1}})}}
\providecommand{\flw}{}\renewcommand{\flw}[1]{{\textrm{FOLLOW}({{#1}})}}
\providecommand{\gen}{}\renewcommand{\gen}[2]{{ {{#1}} \implies {{#2}} }} 
\]
</div>

Do you mean something above didn’t work? But something else below did? Everything in your post was ‘following’ that line so it was unclear.
In other words, which one is ‘this’ that did work and the one or more that didn’t?