3

In my attempt to make my library zx-calculus based on tikz & tikzcd compatible with tikz externalize (to save compilation time), I've basically been using this solution https://tex.stackexchange.com/a/362104/116348 except that I wrap my own library inside it instead of tikzcd.

It works fine so far, but this solution defines globally:

\def\temp{&} \catcode`&=\active \let&=\temp

otherwise the compilation does not treat the & symbol correctly.

I have to admit that I don't fully understand how this lines works (I would be curious if you could let me know), however I'm worried that the changes are global to the whole file. I remember having issues with quantikz that redefine this very same symbol globally (maybe for that reason) and that creates errors when using other packages like tabularray.

Is there any solution to redefine this locally? I tried to move it inside the \mytikzcdcontext function, but without much success.

MWE:

\documentclass{article}

\usepackage{tikz, environ, etoolbox} \usetikzlibrary{cd, external} \tikzexternalize % activate the following such that you can check the macro expansion in % *-figure0.md5 manually %\tikzset{external/up to date check=diff}

%%% How to avoid redefining this globally? \def\temp{&} \catcode`&=\active \let&=\temp

\newcommand{\mytikzcdcontext}[2]{ \begin{tikzpicture}[baseline=(maintikzcdnode.base)] \node (maintikzcdnode) [inner sep=0, outer sep=0] {\begin{tikzcd}[#2] #1 \end{tikzcd}}; \end{tikzpicture}}

\NewEnviron{mytikzcd}[1][]{% % In the following, we need \BODY to expanded before \mytikzcdcontext % such that the md5 function gets the tikzcd content with \BODY expanded. % Howerver, expand it only once, because the \tikz-macros aren't % defined at this point yet. The same thing holds for the arguments to % the tikzcd-environment. \def\myargs{#1}% \edef\mydiagram{\noexpand\mytikzcdcontext{\expandonce\BODY}{\expandonce\myargs}}% \mydiagram% }

\begin{document}

\begin{equation} \begin{mytikzcd}[row sep=huge,baseline = (B.base)] A \arrow[rd] \arrow[r, "\varphi"] & |[alias=B]| B \ & C \end{mytikzcd} \hbox{sharing a baseline with } B \end{equation}

\end{document}

For references, here is what I've been trying to do with my library:

\documentclass[options]{article}

\usepackage{tikz} \makeatletter %%% Download this at https://github.com/leo-colisson/zx-calculus \input{tikzlibraryzx-calculus.code.tex} \makeatother \usetikzlibrary{external} \tikzexternalize % activate!

\NewExpandableDocumentCommand\zxE{O{}m}{ \begin{tikzpicture}[baseline=(tmpdirty.base)] \nodeinner sep=0pt,outer sep=0pt{\begin{ZX}[#1] #2 \end{ZX}}; \end{tikzpicture} }

%% Use myZXE instead, this fails in math environment, no idea why. \NewDocumentEnvironment{ZXE}{O{}+b}{% \def\myargs{#1}% \def\mybody{#2}% \edef\mydiagram{\noexpand\zxE[\expandonce\myargs]{\expandonce\mybody}}% \mydiagram% }

\usepackage{environ} \NewEnviron{myZXE}[1][]{% % In the following, we need \BODY to expanded before \mytikzcdcontext % such that the md5 function gets the tikzcd content with \BODY expanded. % Howerver, expand it only once, because the \tikz-macros aren't % defined at this point yet. The same thing holds for the arguments to % the tikzcd-environment. \def\myargs{#1}% \edef\mydiagram{\noexpand\zxE[\expandonce\myargs]{\expandonce\BODY}}% \mydiagram% }

\NewDocumentEnvironment{myZXEw}{}{% \bgroup% \def\temp{&} \catcode`&=\active \let&=\temp% \begin{myZXE}% }{% \end{myZXE}% \egroup }

\begin{document}

%% Redefine locally? \def\temp{&} \catcode`&=\active \let&=\temp%

Works: $x = \zxE[math baseline=kk]{ \zxX{\alpha} & \zxZ{\beta}\ \zxZ[a=kk]{} }$.

Works: $x = $\begin{ZXE}[math baseline=kk] \zxX[a=kk]{\epsilon} & \zxX{\epsilon}\ \zxZ{abcd} \end{ZXE}

% % Fails: % $x = \begin{ZXE}[math baseline=kk] % \zxX[a=kk]{\epsilon}\ % \zxZ{} % \end{ZXE}$

Works: $x = \begin{myZXEw}[math baseline=kk] \zxX[a=kk]{\delta} & \zxZ{\alpha}\ \zxZ{} \end{myZXE}$

\end{document}

tobiasBora
  • 8,684
  • 3
    unrelated but \NewExpandableDocumentCommand\zxE isn't going to be expandable since it is a tikzpicture Also why use the (ancient) environ \NewEnviron form when you are already using the b option from \NewDocumentEnvironment which does the same thing, but better? – David Carlisle Feb 04 '22 at 09:46
  • Thanks, I used expandable for no reasons, thanks. Concerning \NewEnviron, this is visible in my second MWE: I have no idea why but NewDocumentEnvironment fails in the math environment in my precise example (see the commented "fail" part). If you know what's wrong I'm curious to know. – tobiasBora Feb 04 '22 at 10:05

1 Answers1

5

Do you mean something like this?

The & in the body are first replaced with active &.

\documentclass{article}

\usepackage{tikz} \usetikzlibrary{cd, external} \tikzexternalize % activate the following such that you can check the macro expansion in % *-figure0.md5 manually %\tikzset{external/up to date check=diff}

% simpler to define a helper macro outside \ExplSyntaxOff % because of spaces; we'll define an internal expl3 version later \newcommand{\mytikzcdcontext}[2]{ \begin{tikzpicture}[baseline=(maintikzcdnode.base)] \node (maintikzcdnode) [inner sep=0, outer sep=0] {% \begin{tikzcd}[#1] #2 \end{tikzcd}% }; \end{tikzpicture}% }

\ExplSyntaxOn

\NewDocumentEnvironment{mytikzcd}{O{}+b} { \tl_set:Nn \l_tmpa_tl { #2 } \regex_replace_all:nnN { & } { \cA& } \l_tmpa_tl \tobias_bora_mytikzcd:nV { #1 } \l_tmpa_tl } {}

\cs_set_eq:NN \tobias_bora_mytikzcd:nn \mytikzcdcontext \cs_generate_variant:Nn \tobias_bora_mytikzcd:nn { nV }

\ExplSyntaxOff

\begin{document}

\begin{equation} \begin{mytikzcd}[row sep=huge,baseline = (B.base)] A \arrow[rd] \arrow[r, "\varphi"] & |[alias=B]| B \ & C \end{mytikzcd} \mbox{sharing a baseline with } B \end{equation}

\end{document}

enter image description here

Are you sure you want nested tikzpictures?

egreg
  • 1,121,712
  • Thanks a lot! I'm doing some tests right now, but it seems to work fairly well. I'm also trying to adapt it to make it work for macros instead of environments. Btw, this replacement functionality seems to be usable to use & inside function as well, avoiding the dirty construction provided in https://tex.stackexchange.com/a/611535/116348 , is it correct? – tobiasBora Feb 08 '22 at 09:23
  • Concerning nested pictures, I would love to avoid it, but I want a solution which is simple to maintain (so patching tikzcd directly is not a solution as any change in the tikzcd library would break my library). That said, if you know a nice solution which is easy to maintain, I'd love to hear it. Also, can I have nasty side-effect in this simple wrapper, or is it relatively safe to nest tikz pictures in that scenario? – tobiasBora Feb 08 '22 at 09:26
  • I can confirm that this method also works for https://tex.stackexchange.com/questions/1111/problem-with-defining-shortcuts-for-tikz-matrices/611535 I added an answer. – tobiasBora Feb 08 '22 at 11:25
  • Btw, is there any reason you don't use the second code you provided here https://tex.stackexchange.com/questions/619960/use-inside-commands/619983? I tried it and it also works, and the code is even simpler. – tobiasBora Feb 09 '22 at 20:37