3

Several babel modules (e.g. the ngerman one) make active the " character, and this is the source of troubles with the tikz-cd package and the tikz' babel library may be not enough (see e.g. this question).

As a workaround, I can insert \shorthandoff{"} and \shorthandon{"} respectively before and after the tikzcd environments. But, because this becomes tedious, I would want to automate this with \AtBeginEnvironment{tikzcd} and \AfterEndEnvironment{tikzcd}. But this hasn't any effect: in the following MCE, the compilation fails at the second tikzcd environment.

\documentclass[
, ngerman
, english
]{article}
\usepackage{tikz-cd}
\usepackage{babel}

\usetikzlibrary{babel}

\begin{document}

\shorthandoff{"}% \fbox{% \begin{tikzcd}[ampersand replacement=&] X\ar[-stealth,r,swap,"p" ] & Y \ar[-stealth,l,swap,bend right=30,"s"] \end{tikzcd} } \shorthandon{"}%

\AtBeginEnvironment{tikzcd}{% \shorthandoff{"}% } \AfterEndEnvironment{tikzcd}{% \shorthandon{"}% } \fbox{% \begin{tikzcd}[ampersand replacement=&] X\ar[-stealth,r,swap,"p" ] & Y \ar[-stealth,l,swap,bend right=30,"s"] \end{tikzcd} } \end{document}

Denis Bitouzé
  • 9,652
  • 4
  • 27
  • 85
  • 2
    your tikzcd is in an argument, and so catcode are fixed. – Ulrike Fischer Jun 16 '21 at 16:32
  • 1
    @UlrikeFischer Thanks. But never mind: my attempt would fail in any case since \shorthandoff{"} should be not before \begin{tikzcd}, but before (in the example) \fbox :$ – Denis Bitouzé Jun 16 '21 at 16:50
  • Maybe with BeforeBeginEnvironment, it woulld work? – Bernard Jun 16 '21 at 18:49
  • @Bernard In fact, it is BeforeBeginEnvironment that I had in mind (in symmetry with \AfterEndEnvironment) and wrongly mentioned \AtBeginEnvironment. But neither of them works. – Denis Bitouzé Jun 16 '21 at 19:29
  • It looks like the problem is not tikzcd related because simple \shorthandoff{"} does not work inside \fbox. You can check this by comparing \fbox{\shorthandoff{"}-""-} with \shorthandoff{"}\fbox{-""-}. – Kpym Jun 19 '21 at 16:56
  • @Kpym IMO, tikz-cd is partially the culprit as it heavily relies on ", which is a pain since this character is active with many babel's languages. And \documentclass{article}\usepackage[ngerman,english]{babel}\begin{document}\fbox{"Foo"}\end{document} compiles like a charm. – Denis Bitouzé Jun 20 '21 at 13:00
  • @DenisBitouzé What I'm saying is that you have no chance to solve the problem with \AtBeginEnvironment because this will insert \shorthandoff{"} inside the \fbox and it will not work (like in my previous example). If you wan to use tikzcd inside \fbox probably you should redefine \fbox in a way to add \shorthandoff{"} before it. – Kpym Jun 20 '21 at 15:51
  • @Kpym Ah, OK. That's what I said in the comment above, answering the Ulrike's one :) – Denis Bitouzé Jun 20 '21 at 19:17

1 Answers1

2

TikZ can't do much when it is part of an argument which “fixes” the catcodes (the argment is read already).

You could define your own box macro that – before it grabs the argument – switches of the shorthands and only then grabs it. For example:

\newcommand*\BitouzeBox{\begingroup\shorthandoff{"}\BitouzeBoxInternal}
\newcommand*\BitouzeBoxInternal[1]{\fbox{#1}\endgroup}

which you can use as

\BitouzeBox{%
  \begin{tikzcd}[ampersand replacement=\&]
    X \ar[-stealth, r, swap, "p" ] \&
    Y \ar[-stealth, l, swap, bend right=30, "s"]
  \end{tikzcd}%
}

without having to worry about turning off shorthands. (However, that still means you can't use babels shorthands inside the diagram but you can always use \babelshorthand{"-}.)

However, if all you need is a box around your CD then have TikZ draw them.
In the code below I'm defining a style fbox that is to be used as an option to a tikzpicture or the tikzcd environment which draws a \fbox around your picture. I'm explicitly using the same length that are used by \fbox so that the outcome is the same.

The backgrounds library offers similar keys and more customization.

Code

\documentclass[ngerman,english]{article}
\usepackage{tikz-cd}
\usepackage{babel}
\usetikzlibrary{babel}
\newcommand*\BitouzeBox{\begingroup\shorthandoff{"}\BitouzeBoxInternal}
\newcommand*\BitouzeBoxInternal[1]{\fbox{#1}\endgroup}
\tikzset{fbox/.style={
  /tikz/execute at end picture={\draw[line width=\fboxrule]
              ([shift={(-\fboxsep-.5\pgflinewidth,-\fboxsep-.5\pgflinewidth)}]
                                       current bounding box.south west)
    rectangle ([shift={( \fboxsep+.5\pgflinewidth, \fboxsep+.5\pgflinewidth)}]
                                       current bounding box.north east);}}}
\begin{document}

\shorthandoff{"}% \fbox{% \begin{tikzcd}[ampersand replacement=&] X\ar[-stealth,r,swap,"p" ] & Y \ar[-stealth,l,swap,bend right=30,"s"] \end{tikzcd}% ← ! }

\shorthandon{"}% \BitouzeBox{% \begin{tikzcd}[ampersand replacement=&] X \ar[-stealth, r, swap, "p" ] & Y \ar[-stealth, l, swap, bend right=30, "s"] \end{tikzcd}% ← ! }

\begin{tikzcd}[fbox] % no ampersand replacement anymore! X \ar[-stealth, r, swap, "p" ] & Y \ar[-stealth, l, swap, bend right=30, "s"] \end{tikzcd} \end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821
  • Of course, we could also use another character instead of " for the labels but that's unnecessary work when the babel library already exists and helps a good deal. – Qrrbrbirlbel Nov 19 '22 at 13:51