# Passing nodes as parameters to a macro in TikZ

I would like to define a macro which would take two nodes as arguments and "connect" them using a third, predefined node. Like this:

\documentclass{minimal}

\usepackage{tikz}
\usetikzlibrary{shapes,positioning,fit}

\newcommand{\diamondconn}[3]{
\node[diamond, draw, innter sep=2pt] (diamond) { #1 };
% get the references to #2 and #3 and position them
% on the left and right side of the conn' node
}

\begin{document}

\begin{tikzpicture}
\node[diamond, draw, inner sep=2pt] (diamond) { conn };
\node[draw, left=0pt of diamond.west] { foo };
\node[draw, circle, right=0pt of diamond.east] { bar };
\end{tikzpicture}

% I would like to write this:
\begin{tikzpicture}
\diamondconn{conn}{
\node[draw, rectangle] { foo };
}{
\node[draw, circle] { bar };
}
\end{tikzpicture}

\end{document}


I know I could do it backwards, i.e. define a macro for the connecting node and insert it when needed, I am just curious if the first option is possible as well.

-
I you would write it as \diamondconn{conn}{[draw, rectangle] { foo }}{[draw, circle] { bar }}, you could then use \node [left=0pt of diamond.west] #2; \node [right=0pt of diamond.east] #3; . The \node should support double options. –  Martin Scharrer May 25 '11 at 17:50
@Martin: Shouldn't this be an answer? –  Jake May 25 '11 at 18:08
@Jake: Yeah, I wasn't sure if I understood the OP correctly. I might want to use the full \node ... ; syntax. Also I'm at the rep cap for today anyway ;-) –  Martin Scharrer May 25 '11 at 18:35

I assume you want to keep the node definitions you pass as arguments independent of what happens inside the macro (so you don't want to explicitly use left of=diamond.west in the node definition). In order to achieve this, you can wrap the nodes passed in scope environments inside the macro and "inject" the positioning options, or, as Martin Scharrer suggests, use \tikzset inside curly braces to set the options locally:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{shapes,positioning,fit}

\newcommand{\diamondconn}[3]{

\node[diamond, draw, inner sep=2pt] (diamond) { #1 };
{\tikzset{every node/.style={left=0pt of diamond.west}} #2 }
{\tikzset{every node/.style={right=0pt of diamond.east}} #3 }
}

\begin{document}

\begin{tikzpicture}
\diamondconn{conn}{
\node[draw, rectangle] { foo };
}{
\node[draw, circle] { bar };
}
\end{tikzpicture}

\end{document}

-
I agree. You could also use {\tikzset{every node/.style={...}} #2} etc. if you want to avoid the scope. But it should be .append style anyway, otherwise existing settings will be overwritten. (Also, please don't use the minimal class for minimal example, even when the name sounds like it.) –  Martin Scharrer May 25 '11 at 17:55
@Martin: Sorry about the minimal class, I missed that when I copied the MWE. Good point about the \tikzset, that's definitely less tedious. Two things about the .style/.append style: 1. In this case, wouldn't you want to overwrite options, e.g. if for some reason the nodes passed as arguments contain a different positioning option? 2. It seems neither .style nor .append style actually manage to overwrite an option in this setup (I tried changing the shape of the first node, and it had no effect). –  Jake May 25 '11 at 18:07
I meant that every node/.style will overwrite an "global" every node/.style, e.g. if you use \begin{tikzpicture}[every node/.style={outer sep=5pt,blue}] then this wouldn't be in effect for the two side nodes if you use every node/.style. You might not be able to overwrite the options passed to \node because every node might be executed before that options. –  Martin Scharrer May 25 '11 at 18:34
\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning,fit}

\newcommand{\diamondconn}[3]{%
\node[diamond, draw, inner sep=2pt] (diamond) { #1 };
#2#3 }

\begin{document}
\begin{tikzpicture}
\diamondconn{conn}{
\node[draw, left=0pt of diamond.west] { foo };
}{%
\node[draw, circle, right=0pt of diamond.east] { bar };
}
\end{tikzpicture}
\end{document}


-
This doesn't make sense. If you only use #2#3 in the macro then there is no reason to have the arguments in the first place. –  Martin Scharrer May 25 '11 at 17:48
I agree that my answer doesn't make sense but the question is very strange and I think to put \node in arguments doesn't make sense too. –  Alain Matthes May 25 '11 at 20:35
I agree, having the full \note` code in the argument is quite strange. –  Martin Scharrer May 25 '11 at 20:39