2

This question is indeed very similar to Creating a command that concatenates an input string token by token, but the solution probably looks different and I have difficulties reading up on the necessary commands (the resources all seem to be very technical and hard to get into).

Using expl3 and tikz-cd I want to convert a string A_1;f_1;A_2;f_2;...;A_n (stored in #1) to a diagram:

\begin{tikzcd}
A_1 \ar[r, "f_1"] & A_2 \ar[r, "f_2"] & ... & A_n
\end{tikzcd}

The difficulty here is of course, that the behavior of my "parser" switches at every token. How can I accomplish this?

2 Answers2

3

There are a few problems; first you need ampersand replacement, because you're calling tikzcd as part of a macro.

Second, you need to build the body of the diagram before using it.

The strategy is to split the input in a sequence, then mapping it but distinguishing between odd and even indexed entries.

\documentclass{article}
\usepackage{xparse,tikz-cd}

\ExplSyntaxOn
\NewDocumentCommand{\exactsequence}{ O{} m }
 {
  \perko_exactsequence:nn { #1 } { #2 }
 }

\seq_new:N \l_perko_exactsequence_data_seq
\tl_new:N \l_perko_exactsequence_body_tl

\cs_new_protected:Nn \perko_exactsequence:nn
 {
  \seq_set_split:Nnn \l_perko_exactsequence_data_seq { ; } { #2 }
  \tl_set:Nn \l_perko_exactsequence_body_tl
   {
    \begin{tikzcd}[ampersand~replacement=\&,#1]
   }
  \int_step_inline:nnnn { 1 } { 1 } { \seq_count:N \l_perko_exactsequence_data_seq }
   {
    \int_if_odd:nTF { ##1 }
     {
      \tl_put_right:Nx \l_perko_exactsequence_body_tl
       {
        \seq_item:Nn \l_perko_exactsequence_data_seq { ##1 }
       }
     }
     {
      \tl_put_right:Nx \l_perko_exactsequence_body_tl
       {
        \exp_not:N \ar [ r , "\seq_item:Nn \l_perko_exactsequence_data_seq { ##1 }" ]
        \exp_not:N \&
       }
     }
   }
  \tl_put_right:Nn \l_perko_exactsequence_body_tl { \end{tikzcd} }
  \tl_use:N \l_perko_exactsequence_body_tl
 }
\ExplSyntaxOff

\begin{document}

\[
\exactsequence{A;a;B;b;C;c;D}
\]

\[
\exactsequence[column sep=small]{A;a;B;b;C;c;D}
\]

\end{document}

The optional argument is for options to tikzcd.

enter image description here

egreg
  • 1,121,712
2

enter image description here

\documentclass{article}
\usepackage{tikz-cd}

\begin{document}



\begin{tikzcd}
A_1\ar[r, "f_1"]& A_2\ar[r, "f_2"]& A_3\ar[r, "f_3"]& A_4
\end{tikzcd}


\bigskip



{\makeatletter\catcode`\&\active
\gdef\zz#1{\toks0{\begin{tikzcd}}\zza#1;!;}
\gdef\zza#1;{\toks0\expandafter{\the\toks0 #1}\zzb}
\gdef\zzb#1;{\ifx!#1%
\expandafter\@firstoftwo\else
\expandafter\@secondoftwo
\fi
{\the\toks0 \end{tikzcd}}%
{\toks0\expandafter{\the\toks0 \ar[r, "#1"]&}\zza}%
}
}


\zz{A_1;f_1;A_2;f_2;A_3;f_3;A_4}

\end{document}
David Carlisle
  • 757,742