7

The document I'm writing is full of diagrams of arrows, therefore I'd like to create a newcommand \diagram that avoids me to write every time the settings of the tikzpictures. I put

\newcommand{\diagram}[2]{ 
\begin{tikzpicture} [baseline=(current bounding box.center),
grade/.style={sloped,fill=white,inner sep=1pt,font=\tiny},
equal/.style={-,double distance=3pt}]
\matrix (m) [matrix of math nodes, 
             row sep=2em, column sep=2em,
             text height=1.5ex, text depth=0.25ex]
{ #1 };
  #2
\end{tikzpicture}
}

so that in the code i should just write \diagram{%matrix_of_nodes}{%paths}.

For example

\diagram{A & B \\
         C & D \\}
        {\path[->,font=\scriptsize]
         (m-1-1) edge (m-2-2);}

But when I compile the file (I'm using TexMaker) it returns me the error

"! Package pgfbasematrix Error: Single ampersand used with wrong catcode."

And it highlights the line where the edge is defined. This problem does not occur if I write the whole script, so I don't understand where the problem could be.

Can anybody help me?

  • 1
    I think it is a bad idea to pass the entire tikz code as an argument. What about using \newenvironment{diagram} instead of a macro? – Bordaigorl Jul 16 '15 at 12:57
  • That's what I was about to suggest: it seems a much more natural way of doing this. – cfr Jul 16 '15 at 12:58
  • @cfr still, I just realised, the problem arises because of the first argument, which contains ampersands... – Bordaigorl Jul 16 '15 at 13:02
  • @Bordaigorl Yes. You can get around that but I think an environment would be better here anyway. – cfr Jul 16 '15 at 13:05
  • I'm sorry, I'm quite new to latex and I didn't know of that possibility, nor that having ampersands within an argument could be a problem (I also created a \newcommand for matrices and it worked fine). Thanks for your help anyway, I'll just create a \newenvironment. – LK512 Jul 16 '15 at 13:07
5

The problem arises from the use of & in the argument, which is problematic since they are a special character and PGF wants to treat them in a special way.

A solution could be to use environments (which I find nicer anyway) and a trick to avoid needing an argument:

\documentclass[tikz,border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}
\newenvironment{diagram}{
    \begin{tikzpicture} [baseline=(current bounding box.center),
    grade/.style={sloped,fill=white,inner sep=1pt,font=\tiny},
    equal/.style={-,double distance=3pt}]
        \matrix (m) [matrix of math nodes,
                     row sep=2em, column sep=2em,
                     text height=1.5ex, text depth=0.25ex]
}{
    \end{tikzpicture}
}

\begin{document}
    \begin{diagram}{A & B \\ C & D \\};
        \path[->,font=\scriptsize]
                 (m-1-1) edge (m-2-2);
    \end{diagram}
\end{document}

If you want you can also change the character used to delimit columns using the ampersand replacement key:

\documentclass[tikz,border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}
\newenvironment{diagram}[1]{
    \begin{tikzpicture} [ampersand replacement=\&,baseline=(current bounding box.center),
    grade/.style={sloped,fill=white,inner sep=1pt,font=\tiny},
    equal/.style={-,double distance=3pt}]
        \matrix (m) [matrix of math nodes,
                     row sep=2em, column sep=2em,
                     text height=1.5ex, text depth=0.25ex]{#1};
}{
    \end{tikzpicture}
}

\begin{document}

\begin{diagram}{A \& B \\ C \& D \\}
    \path[->,font=\scriptsize]
             (m-1-1) edge (m-2-2);
\end{diagram}
\end{document}

note the absence of the ; after the argument and the use of \& instead of &.

With this trick you can also define the macro as you originally intended:

\documentclass[tikz,border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}
\newcommand{\diagram}[2]{
    \begin{tikzpicture} [ampersand replacement=\&,baseline=(current bounding box.center),
    grade/.style={sloped,fill=white,inner sep=1pt,font=\tiny},
    equal/.style={-,double distance=3pt}]
        \matrix (m) [matrix of math nodes,
                     row sep=2em, column sep=2em,
                     text height=1.5ex, text depth=0.25ex]{#1};
        #2
    \end{tikzpicture}
}

\begin{document}
    \diagram{A \& B \\ C \& D \\}{\path[->,font=\scriptsize] (m-1-1) edge (m-2-2);}
\end{document}

But I'd still use environments, it just feels more natural and you avoid troubles when #2 too has special characters in it.

If you did that just to avoid repetition in style defs:

You could also reduce redundancy by using styles:

\documentclass[tikz,border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}

\tikzset{
    diagram/.style = {
        baseline=(current bounding box.center),
        grade/.style={sloped,fill=white,inner sep=1pt,font=\tiny},
        equal/.style={-,double distance=3pt},
        every matrix/.style={
            matrix of math nodes,
            row sep=2em, column sep=2em,
            text height=1.5ex, text depth=0.25ex
        }
    }
}

\begin{document}
    \begin{tikzpicture}[diagram]
        \matrix (m) {A & B \\ C & D \\};
        \path[->,font=\scriptsize] (m-1-1) edge (m-2-2);
    \end{tikzpicture}
\end{document}

Now the repetition for each diagram is minimal and you have a lot more flexibility.

  • Your first solution was more than adequate so solve my problem, but thanks for the further explanation, it's always useful. – LK512 Jul 16 '15 at 13:58
1

Using ampersand replacement=\& seems the best strategy; however, I recommend you to give tikz-cd a try:

\documentclass[tikz,border=10pt]{standalone}
\usepackage{tikz-cd}

\begin{document}

\begin{tikzcd}[row sep=2em,column sep=2em]
  A \arrow[dr] & B \\
  C & D
\end{tikzcd}

\end{document}

enter image description here

  • Thank you for the advice! However i needed to "compress" the environment because I use special edge/node styles that i have to declare every time at the beginning of the diagram, as you can see from the code i posted (the small diagram i drew was just an example to show the syntax of my new command). If tikzcd allows to do that with less effort I'm definitely interested to know about it. – LK512 Jul 16 '15 at 13:56
  • @LK512 As far as I know, tikz-cd eventually translates everything in terms of \matrix and edge connections. – egreg Jul 16 '15 at 14:00
  • @LK512 if you are mainly worried about setting styles at the start you can have a look in the manual how to define your own that can be used as a shortcut, just as in my diagram/.style={...your styles...} – Bordaigorl Jul 16 '15 at 14:00
  • @LK512 I updated my solution to show you what I mean – Bordaigorl Jul 16 '15 at 14:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.