5

I have the following piece of code

\documentclass{article}
\usepackage{tikz}
\def\pos{5,5}    
\begin{document}
 \begin{tikzpicture}    
  \node (b)  at (0,0) {test};
  \node (a) \ifx\pos\pgfutil@empty\else at(\pos)\fi {something};
 \end{tikzpicture}
\end{document}

I want to test if the macro \pos holds a position or not and in case it does I want to use it to print the node. However, when I compile the example above I get some errors in the way of:

Package tikz Error: A node must have a (possibly empty) label text.

Use of \@next doesn't match its definition.

What am I doing wrong? Or in which way can I achieve my goal of testing the macro for display?

Roelof Spijker
  • 17,663
  • 5
  • 55
  • 63
adn
  • 11,233

2 Answers2

4

When TikZ looks for an at specification after \node (a), it doesn't expand tokens. So in your case it finds \ifx which it doesn't like.

If you really need such a test, the following hack works:

\begin{tikzpicture}
  \node (b)  at (0,0) {test};
  \begingroup\edef\x{\endgroup\noexpand\node (a) \ifx\pos\empty\else at(\pos)\fi}
  \x {something};
\end{tikzpicture}

as it expands the conditional before TikZ can see \node.

Note that you can't use \pgfutil@empty unless you set \makeatletter before the tikzpicture environment (it seems overkill to me).

egreg
  • 1,121,712
  • I don't mean to be overly critical, and this is a nice showcase of a clever trick, but is the \begingroup thing really necessary? So what if another macro name gets defined, or \x gets overwritten? It seems more instructive to give the minimal effective code performing "compute first, then expand the result". – Ryan Reich Feb 09 '12 at 09:37
  • With this code, you're sure that nothing will be overwritten. The only disallowed tokens are \noexpand\x in the replacement text, which wouldn't be meaningful anyway. – egreg Feb 09 '12 at 09:47
  • Thanks for your comments. However, you say "if you really need such a test," is there any other way to achieve the same result but in a different way? – adn Feb 09 '12 at 11:01
  • @egreg Even \noexpand\x can be used in the replacement text without trouble. The definition of \x that you created only lives from the end of the \edef to the end of the group, i.e., just long enough to expand that \x once. – Bruno Le Floch Feb 09 '12 at 11:24
  • @BrunoLeFloch I had this doubt, indeed. Thanks. – egreg Feb 09 '12 at 11:27
3

To answer the part:

Or in which way can I achieve my goal of testing the macro for display?

Here's a method using pgfkeys to define a style tripos (with apologies to any Cambridge graduates present) which examines \pos to see if it is empty or not, and if not then it uses \pgfkeys to call the at key to set the node's position.

\documentclass{article}
\usepackage{tikz}
\def\pos{5,5}    

\tikzset{tripos/.code={%
    \unless\ifx\pos\empty
    \pgfkeys{/tikz/at=(\pos)}
    \fi
  }
}

\begin{document}
 \begin{tikzpicture}    
  \node (b)  at (0,0) {test};
  \node[tripos] (a) {something};
 \end{tikzpicture}
\end{document}

(As David Carlisle notes in his comment on your question, using the @ requires \makeatletter ... \makeatother wizardry. As you're using LaTeX, we can test against \empty instead of \pgfutil@empty and so avoid this issue.)

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751