4

When creating a style with args using \tikzset, I have no problem creating "aliases" with args, as long as those args appear in the value part of a key=value, like xshift=#1. What I want to do is take an argument, use a command to process it, and have that command generate key-values. This however is not working as I expect.

\documentclass[tikz,border=3mm]{standalone}

\usetikzlibrary{positioning}

\NewDocumentCommand{\processxyshift}{m}{%
% in my use, I'm goinng to do something more fancy, hence why I want to use a command
xshift=#1cm,yshift=#1cm
}

\tikzset{
xs/.style={xshift=#1}  % #1 appearing in the value works as long as it's preceded by a key
xys/.style={\processxyshift{#1}} % but if I want some command to print a key=value output, it fails
}

\begin{document}
\begin{tikzpicture}
\node(start) at (0,0) {Hello World};
\node[anchor=west](end)   at ([xs=1]start.east) {Over here!};  % works
\node[anchor=west](end)   at ([xys=2]start.east) {Over here!}; % this does not work
\end{tikzpicture}
\end{document}

3 Answers 3

6

You want .estyle, but \newcommand, not \NewDocumentCommand. Or \NewExpandableDocumentCommand.

\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}

\newcommand{\processxyshift}[1]{%
  % in my use, I'm going to do something more fancy
  xshift=#1cm,yshift=#1cm
}

\tikzset{
  xs/.style={xshift=#1},
  xys/.estyle={\processxyshift{#1}},
}

\begin{document}

\begin{tikzpicture}
\node(start) at (0,0) {Hello World};
\node[anchor=west](end) at ([xs=1]start.east) {Over here!};
\node[anchor=west](end) at ([xys=2]start.east) {Over here!};
\end{tikzpicture}

\end{document}

enter image description here

5

Alternatively to .estyle (which fully expands the input) you can also expand the input just once using the .expand once handler. In the example it doesn't make a difference, but if your macro expands to stuff that shouldn't expand further you should use .expand once:

\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}

\newcommand{\processxyshift}[1]{%
  % in my use, I'm going to do something more fancy
  xshift=#1cm,yshift=#1cm
}

\tikzset{
  xs/.style={xshift=#1},
  xys/.style/.expand once={\processxyshift{#1}},
}

\begin{document}

\begin{tikzpicture}
\node(start) at (0,0) {Hello World};
\node[anchor=west](end) at ([xs=1]start.east) {Over here!};
\node[anchor=west](end) at ([xys=2]start.east) {Over here!};
\end{tikzpicture}

\end{document}
4

You can use the .code handler and \pgfkeysalso:

\documentclass[tikz,border=3mm]{standalone}

\usetikzlibrary{positioning}

\newcommand{\processxyshift}[1]{%
  % in my use, I'm goinng to do something more fancy, hence why I want to use a command
  \pgfkeysalso{xshift=#1cm,yshift=#1cm}
}

\tikzset{
  xs/.style={xshift=#1},
  xys/.code={\processxyshift{#1}},
  xys2/.code={
    % in my use, I'm goinng to do something more fancy, hence why I want to use a command
    \typeout{#1}
    \pgfkeysalso{xshift=#1cm,yshift=#1cm}
  }
}

\begin{document}
\begin{tikzpicture}
\node(start) at (0,0) {Hello World};
\node[anchor=west](end)   at ([xs=1]start.east) {Over here 1!};  % works
\node[anchor=west](end)   at ([xys=2]start.east) {Over here 2!}; % this does not work
\node[anchor=west](end)   at ([xys2=3]start.east) {Over here 3!}; % this does not work
\end{tikzpicture}
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .